Freika/dawarich · warning

[EventHandlers] Failed to highlight track:

Error message

[EventHandlers] Failed to highlight track:

What it means

Dawarich's MapLibre maps v2 event handler wraps the visual highlight of a clicked track in a defensive try/catch. After a track click it resolves the full feature, stores it as the selected track, and asks LayerManager for the 'tracks' layer to call setSelectedTrack(). Any exception inside that highlight step (layer not registered, map style not ready, layer removed mid-click) is caught and logged with this message; the click flow still continues to load segments and open the timeline.

Source

Thrown at app/javascript/controllers/maps/maplibre/event_handlers.js:678

      if (trackPointFeatures.length > 0) return
    }

    const clickedFeature = e.features[0]
    if (!clickedFeature) return

    const properties = clickedFeature.properties
    const fullFeature = this._getFullTrackFeature(properties) || clickedFeature
    this.selectedTrackFeature = fullFeature

    // Keep the on-map highlight + segment visualization — those are visual
    // feedback for the click itself, independent of the info surface.
    try {
      const tracksLayer = this.controller.layerManager.getLayer("tracks")
      if (tracksLayer?.setSelectedTrack) {
        tracksLayer.setSelectedTrack(fullFeature)
      }
    } catch (err) {
      console.warn("[EventHandlers] Failed to highlight track:", err)
    }
    this._loadTrackSegments(properties.id, fullFeature)

    // Derive the day from the track's start. `start_at` comes from our own
    // serializer as an ISO8601 string — safe to slice the date portion.
    const startAt =
      typeof properties.start_at === "string" ? properties.start_at : null
    const date = startAt ? startAt.slice(0, 10) : null
    const trackId = Number(properties.id)

    document.dispatchEvent(
      new CustomEvent("timeline:open-track", {
        detail: { trackId, date, startAt },
      }),
    )
  }

  /**

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Inspect the error object logged after the message — it names the exact layer or paint property that failed
  2. Gate the highlight on readiness: check layerManager.getLayer('tracks') exists and map.isStyleLoaded() before calling setSelectedTrack
  3. Make TracksLayer.setSelectedTrack defensive: early-return unless this.map.getLayer(this.layerId) exists
  4. If it fires after Turbo navigation, clear handlers in the Stimulus controller's disconnect() so post-teardown clicks cannot reach a dead map

Example fix

// before
const tracksLayer = this.controller.layerManager.getLayer("tracks")
if (tracksLayer?.setSelectedTrack) {
  tracksLayer.setSelectedTrack(fullFeature)
}
// after
const tracksLayer = this.controller.layerManager.getLayer("tracks")
const mapReady = this.controller.map?.isStyleLoaded?.() === true
if (tracksLayer?.setSelectedTrack && mapReady) {
  tracksLayer.setSelectedTrack(fullFeature)
} else {
  console.debug("[EventHandlers] Tracks layer not ready, skipping highlight")
}
Defensive patterns

Strategy: try-catch

Validate before calling

const layer = this.controller.layerManager.getLayer("tracks")
const ready =
  Boolean(layer && typeof layer.setSelectedTrack === "function") &&
  this.controller.map?.isStyleLoaded?.() === true
if (!ready) return // skip the highlight instead of risking a throw

Type guard

/** @param {object} controller @returns {boolean} */
function canHighlightTrack(controller) {
  const layer = controller.layerManager?.getLayer("tracks")
  return Boolean(
    layer &&
    typeof layer.setSelectedTrack === "function" &&
    controller.map &&
    typeof controller.map.getLayer === "function" &&
    controller.map.styleLoaded()
  )
}

Try / catch

try {
  tracksLayer.setSelectedTrack(fullFeature)
} catch (err) {
  // Visual-only feedback: log and keep the click flow going (segments + timeline)
  console.warn("[EventHandlers] Failed to highlight track:", err)
}

Prevention

When it happens

Trigger: Clicking a track before LayerManager.addLayers() has registered the 'tracks' layer (style/tiles still loading); clicking while a style swap or layer toggle removes the layer underneath setSelectedTrack(); a refactor renaming the layer id so getLayer('tracks') returns an unexpected object; map torn down by Turbo navigation while the click handler chain is still running.

Common situations: Users clicking tracks immediately after page load on slow connections; Turbo cache restoring a stale page whose listeners outlive the map; layer ids changed during Maps v2 refactoring; highlight invoked after removeLayer during filter changes.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/629c450b8891c4d9. Report an issue: GitHub.