Skip to content

Troubleshooting

Common issues and their solutions when working with the Route Optimization Map library.

Google Maps Issues

Map Not Displaying

Problem: The map container appears empty or shows a gray area.

Solutions:

  1. Check API Key

    typescript
    // Verify your API key is correct
    const config: MapConfig = {
      apiKey: 'YOUR_ACTUAL_API_KEY', // Not 'YOUR_API_KEY'
    };
  2. Enable Required APIs

    • Go to Google Cloud Console
    • Enable "Maps JavaScript API"
    • Enable "Routes API" (for route optimization)
    • Enable "Places API" (if using places features)
  3. Check Container Size

    css
    .map-container {
      width: 100%;
      height: 600px; /* Must have explicit height */
    }
  4. Wait for Map to Load

    typescript
    // React
    const { mapRef, isReady } = useRouteMap({ apiKey: 'YOUR_API_KEY' });
    
    useEffect(() => {
      if (isReady) {
        console.log('Map is ready');
      }
    }, [isReady]);

API Key Errors

Problem: Console shows "InvalidKeyMapError" or "RefererNotAllowedMapError".

Solutions:

  1. Invalid API Key

    typescript
    // Check for typos, extra spaces, or invalid characters
    const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY?.trim();
  2. Referrer Restrictions

    • In Google Cloud Console, go to API Key restrictions
    • Add your domain to HTTP referrers:
      • localhost:* for development
      • yourdomain.com/* for production
      • *.yourdomain.com/* for subdomains
  3. API Restrictions

    • Ensure the API key has access to required APIs
    • Check quota limits haven't been exceeded

Rate Limiting

Problem: "OVER_QUERY_LIMIT" error appears.

Solutions:

  1. Implement Request Throttling

    typescript
    import { debounce } from 'lodash-es';
    
    const debouncedOptimize = debounce(async (request: OptimizationRequest) => {
      await optimizer.optimize(request);
    }, 1000);
  2. Add Retry Logic

    typescript
    async function optimizeWithRetry(
      request: OptimizationRequest,
      maxRetries = 3
    ): Promise<OptimizationResponse> {
      for (let i = 0; i < maxRetries; i++) {
        try {
          return await optimizer.optimize(request);
        } catch (error) {
          if (error.message.includes('OVER_QUERY_LIMIT')) {
            await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1000));
            continue;
          }
          throw error;
        }
      }
      throw new Error('Max retries exceeded');
    }
  3. Check Billing

    • Verify billing is enabled in Google Cloud Console
    • Check if daily quota limits have been reached

React Issues

Map Not Rendering in React

Problem: Map doesn't appear in React component.

Solutions:

  1. Check Ref Initialization

    typescript
    function MapComponent() {
      const { mapRef, isReady } = useRouteMap({
        apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY
      });
    
      // ✅ Correct - ref is attached
      return <div ref={mapRef} style={{ width: '100%', height: '600px' }} />;
    
      // ❌ Wrong - missing ref
      // return <div style={{ width: '100%', height: '600px' }} />;
    }
  2. Environment Variables

    bash
    # .env
    REACT_APP_GOOGLE_MAPS_API_KEY=your_api_key_here
    
    # Next.js
    NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_api_key_here
    
    # Vite
    VITE_GOOGLE_MAPS_API_KEY=your_api_key_here
  3. StrictMode Issues

    typescript
    // Remove StrictMode if it causes double initialization
    // index.tsx
    root.render(
      // <React.StrictMode>  // Comment out for testing
        <App />
      // </React.StrictMode>
    );

Infinite Re-renders

Problem: Component re-renders infinitely.

Solutions:

  1. Memoize Callbacks

    typescript
    // ❌ Wrong - Creates new function on every render
    const handleClick = () => console.log('clicked');
    
    // ✅ Correct - Memoized callback
    const handleClick = useCallback(() => {
      console.log('clicked');
    }, []);
  2. Memoize Objects

    typescript
    // ❌ Wrong - New object on every render
    const route = {
      stops: [...],
      options: { ... },
    };
    
    // ✅ Correct - Memoized object
    const route = useMemo(() => ({
      stops: [...],
      options: { ... },
    }), [stops]);
  3. Dependencies Array

    typescript
    // Check useEffect dependencies
    useEffect(() => {
      renderRoute(route);
    }, [route, renderRoute]); // Only re-run when these change

Memory Leaks

Problem: Memory usage increases over time.

Solutions:

  1. Cleanup in useEffect

    typescript
    useEffect(() => {
      const map = initializeMap();
    
      return () => {
        // Always cleanup
        map.destroy();
      };
    }, []);
  2. Remove Event Listeners

    typescript
    useEffect(() => {
      const handleResize = () => {
        map?.resize();
      };
    
      window.addEventListener('resize', handleResize);
    
      return () => {
        window.removeEventListener('resize', handleResize);
      };
    }, [map]);

Vue Issues

Map Not Rendering in Vue

Problem: Map doesn't appear in Vue component.

Solutions:

  1. Template Ref

    vue
    <template>
      <!-- ✅ Correct -->
      <div ref="mapElement" style="width: 100%; height: 600px;" />
    
      <!-- ❌ Wrong - no ref -->
      <!-- <div style="width: 100%; height: 600px;" /> -->
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue';
    import { useRouteMap } from '@route-optimization/vue';
    
    const mapElement = ref<HTMLDivElement>();
    
    const { isReady } = useRouteMap({
      mapElement,
      apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
    });
    </script>
  2. Wait for Element

    typescript
    import { ref, onMounted } from 'vue';
    
    const mapElement = ref<HTMLDivElement>();
    
    onMounted(() => {
      // Element is guaranteed to be available
      const { isReady } = useRouteMap({
        mapElement,
        apiKey: 'YOUR_API_KEY',
      });
    });

Reactivity Issues

Problem: Map doesn't update when data changes.

Solutions:

  1. Use Computed

    typescript
    import { computed, watch } from 'vue';
    
    const route = computed(() => ({
      stops: props.stops,
      options: routeOptions.value,
    }));
    
    watch(route, (newRoute) => {
      renderRoute(newRoute);
    });
  2. Deep Watch

    typescript
    watch(
      () => props.stops,
      (newStops) => {
        updateRoute(newStops);
      },
      { deep: true } // Watch nested changes
    );

Nuxt SSR Issues

Problem: "window is not defined" error in Nuxt.

Solutions:

  1. Use ClientOnly

    vue
    <template>
      <ClientOnly>
        <RouteMapComponent />
      </ClientOnly>
    </template>
  2. Lazy Import

    typescript
    // nuxt.config.ts
    export default defineNuxtConfig({
      components: [
        {
          path: '~/components',
          extensions: ['.vue'],
        },
      ],
    });
    
    // Component
    const RouteMapComponent = defineAsyncComponent(() => import('./RouteMapComponent.vue'));

TypeScript Issues

Type Errors

Problem: TypeScript shows type errors.

Solutions:

  1. Import Types

    typescript
    import type { LatLng, Stop, Route, OptimizationRequest } from '@route-optimization/core';
  2. Type Assertions (Use Sparingly)

    typescript
    // ✅ Prefer type guards
    if (isValidRoute(data)) {
      processRoute(data);
    }
    
    // ⚠️ Use assertions only when necessary
    const route = data as Route;
  3. Generic Types

    typescript
    interface CustomMetadata {
      orderId: string;
      priority: 'low' | 'medium' | 'high';
    }
    
    const stop: Stop<CustomMetadata> = {
      id: '1',
      location: { lat: 13.7563, lng: 100.5018 },
      metadata: {
        orderId: 'ORD-123',
        priority: 'high',
      },
    };

Missing Type Definitions

Problem: "Could not find declaration file" error.

Solutions:

  1. Install Type Definitions

    bash
    npm install --save-dev @types/google.maps
  2. Create Declaration File

    typescript
    // types/google-maps.d.ts
    declare namespace google.maps {
      class Map {
        constructor(element: HTMLElement, options?: MapOptions);
      }
    
      interface MapOptions {
        center?: LatLng;
        zoom?: number;
      }
    }

Optimization Issues

Optimization Fails

Problem: Route optimization returns an error.

Solutions:

  1. Check Request Format

    typescript
    const request: OptimizationRequest = {
      shipments: [
        {
          id: 'shipment-1', // Required
          deliveryLocation: {
            // At least one location required
            latitude: 13.7563,
            longitude: 100.5018,
          },
        },
      ],
      vehicles: [
        {
          id: 'vehicle-1', // Required
          startLocation: {
            // Optional but recommended
            latitude: 13.7563,
            longitude: 100.5018,
          },
        },
      ],
    };
  2. Validate Coordinates

    typescript
    function isValidLatLng(location: OptimizationLocation): boolean {
      return (
        location.latitude >= -90 &&
        location.latitude <= 90 &&
        location.longitude >= -180 &&
        location.longitude <= 180
      );
    }
    
    // Check all locations
    const allLocations = [
      ...request.shipments.flatMap((s) => [s.pickupLocation, s.deliveryLocation]),
      ...request.vehicles.flatMap((v) => [v.startLocation, v.endLocation]),
    ].filter(Boolean);
    
    const allValid = allLocations.every(isValidLatLng);
  3. Check Time Windows

    typescript
    // Ensure times are in ISO 8601 format
    const timeWindow = {
      startTime: '2025-12-12T09:00:00Z', // ✅ Correct
      // startTime: '09:00', // ❌ Wrong
      endTime: '2025-12-12T17:00:00Z',
    };

Slow Optimization

Problem: Route optimization takes too long.

Solutions:

  1. Use RETURN_FAST Mode

    typescript
    const request: OptimizationRequest = {
      shipments: [...],
      vehicles: [...],
      searchMode: 'RETURN_FAST', // Faster but may be less optimal
    };
  2. Reduce Problem Size

    typescript
    // Split large requests into smaller batches
    const batchSize = 50;
    const batches = [];
    
    for (let i = 0; i < shipments.length; i += batchSize) {
      batches.push(shipments.slice(i, i + batchSize));
    }
    
    for (const batch of batches) {
      await optimizer.optimize({
        shipments: batch,
        vehicles: [...],
      });
    }
  3. Show Progress

    typescript
    optimizer.on('progress', ({ progress, step }) => {
      console.log(`${Math.round(progress * 100)}% - ${step}`);
    });

Build Issues

Build Failures

Problem: Build fails with errors.

Solutions:

  1. Clear Cache

    bash
    # npm
    rm -rf node_modules package-lock.json
    npm install
    
    # Yarn
    rm -rf node_modules yarn.lock
    yarn install
    
    # pnpm
    rm -rf node_modules pnpm-lock.yaml
    pnpm install
  2. Check Node Version

    bash
    node --version # Should be >= 18
    
    # Use nvm to switch versions
    nvm use 18
  3. TypeScript Configuration

    json
    // tsconfig.json
    {
      "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "jsx": "react-jsx" // For React
      }
    }

Module Resolution Errors

Problem: "Cannot find module" errors.

Solutions:

  1. Check Import Paths

    typescript
    // ✅ Correct
    import { useRouteMap } from '@route-optimization/react';
    
    // ❌ Wrong
    import { useRouteMap } from '@route-optimization/core';
  2. Verify Package Installation

    bash
    npm list @route-optimization/react
  3. Module Resolution

    json
    // tsconfig.json
    {
      "compilerOptions": {
        "moduleResolution": "node", // or "bundler" for Vite
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true
      }
    }

Runtime Errors

"Cannot read property of undefined"

Problem: Accessing properties on undefined objects.

Solutions:

  1. Optional Chaining

    typescript
    // ✅ Safe
    const location = stop?.location;
    const lat = stop?.location?.lat;
    
    // ❌ Unsafe
    const lat = stop.location.lat;
  2. Null Checks

    typescript
    if (map && isReady) {
      renderRoute(route);
    }
  3. Default Values

    typescript
    const stops = route?.stops ?? [];
    const zoom = config?.zoom ?? 12;

Network Errors

Problem: Network requests fail.

Solutions:

  1. Error Handling

    typescript
    try {
      const result = await optimizer.optimize(request);
    } catch (error) {
      if (error instanceof Error) {
        console.error('Optimization failed:', error.message);
    
        // Handle specific errors
        if (error.message.includes('NETWORK_ERROR')) {
          // Retry or show offline message
        }
      }
    }
  2. Timeout Handling

    typescript
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => reject(new Error('Timeout')), 30000);
    });
    
    const result = await Promise.race([optimizer.optimize(request), timeoutPromise]);

Console Warnings

React Warnings

Problem: "Warning: Can't perform a React state update on an unmounted component".

Solutions:

typescript
import { useEffect, useRef } from 'react';

function useIsMounted() {
  const isMounted = useRef(true);

  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  return isMounted;
}

function MapComponent() {
  const isMounted = useIsMounted();
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then((result) => {
      if (isMounted.current) {
        setData(result);
      }
    });
  }, []);
}

Vue Warnings

Problem: "Warning: Avoid mutating a prop directly".

Solutions:

typescript
// ❌ Wrong
props.stops.push(newStop);

// ✅ Correct
const stops = ref([...props.stops]);
stops.value.push(newStop);

// Or emit event
emit('update:stops', [...props.stops, newStop]);

Debugging Tips

Enable Debug Logging

typescript
// Set debug flag
const config: RouteCalculatorConfig = {
  apiKey: 'YOUR_API_KEY',
  debug: true, // Enable debug logging
};

Chrome DevTools

  1. Network Tab: Check API requests
  2. Console: View errors and logs
  3. Performance: Profile rendering
  4. Memory: Check for leaks

React DevTools

typescript
// Add displayName for better debugging
const RouteMapComponent = () => { ... };
RouteMapComponent.displayName = 'RouteMapComponent';

Vue DevTools

typescript
// Use vue-devtools
// Install: https://devtools.vuejs.org/

Getting Help

If you're still experiencing issues:

  1. Check Documentation

  2. Search Issues

    • Look for similar issues on GitHub
    • Check Stack Overflow
  3. Create an Issue

    • Provide a minimal reproduction
    • Include error messages
    • Share environment details
  4. Community Support

    • Ask in GitHub Discussions
    • Join our Discord server

Next Steps

Released under the MIT License.