Skip to content

🐛 [Bug] App Crashes when Items Fail to Load #409

@mahula

Description

@mahula

🐛 Bug

Problem

The application crashes with TypeError: Cannot read properties of undefined (reading 'map') when any layer's API call fails during startup, making the entire app unusable.

Root Cause

In lib/src/Components/Map/hooks/useItems.tsx, the setItemsApi function uses toast.promise without error handling:

const setItemsApi = useCallback(async (layer: LayerProps) => {
  addLayer(layer)
  const result = await toast.promise(layer.api!.getItems(), {...})  // Throws on error
  result.map((item) => {  // Crashes: result is undefined when API fails
    dispatch({ type: 'ADD', item: { ...item, layer } })
  })
  setallItemsLoaded(true)  // Never executes on error
}, [])

When the API fails: toast.promise throws → execution stops → result is undefined → .map() crashes.

Reproducible Scenarios

Scenario 1: Backend Server Error

  1. Configure backend to return 500 Internal Server Error for /items endpoint
  2. Start the application
  3. Navigate to map page
  4. Result: App crashes immediately with TypeError: Cannot read properties of undefined (reading 'map')

Scenario 2: Network Connectivity Issues

  1. Start the application
  2. Disconnect network/WiFi during item loading
  3. Result: Same crash occurs, app becomes unusable

Scenario 3: Invalid API Configuration

  1. Configure invalid API endpoint in environment variables
  2. Start the application
  3. Result: App crashes on startup, search never works

Scenario 4: Database Connection Issues

  1. Stop the Directus database container
  2. Start the frontend application
  3. Result: App crashes when trying to load layers

Impact

  • Complete app crash during backend downtime/network issues
  • Search becomes permanently broken (no items loaded)
  • Affects 100% of users when backend issues occur
  • App stuck in loading state (allItemsLoaded stays false)

Current Architecture Issues

  • Multiple Layer Loading: Each layer calls setItemsApi independently
  • Single Loading Flag: allItemsLoaded is one boolean for all layers
  • No Partial Loading: One failed layer breaks entire loading mechanism
  • Critical Dependencies: Search and profile features depend on allItemsLoaded

Comprehensive Solution

Phase 1: Immediate Hotfix

const setItemsApi = useCallback(async (layer: LayerProps) => {
  addLayer(layer)
  try {
    const result = await toast.promise(layer.api!.getItems(), {...})
    result.map((item) => {
      dispatch({ type: 'ADD', item: { ...item, layer } })
    })
  } catch (error) {
    console.error(`Failed to load ${layer.name}:`, error)
    // Don't crash - allow app to continue with partial data
  } finally {
    setallItemsLoaded(true) // Always set loaded state
  }
}, [])

Phase 2: Enhanced Error Handling

  • Add layer-specific loading state tracking
  • Implement graceful degradation for partial data loading
  • Provide user feedback for failed layers
  • Add retry mechanisms for failed layers

Benefits

  • ✅ Prevents app crashes immediately
  • ✅ Maintains app functionality with partial data
  • ✅ Provides foundation for better error handling
  • ✅ No breaking changes to existing components

Testing

  • Verify app continues working when backend returns 500 errors
  • Test with network connectivity issues
  • Confirm search works with partially loaded data
  • Validate error toast notifications appear

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions