Freika/dawarich · warning

[Realtime Controller] Points layer not found

Error message

[Realtime Controller] Points layer not found

What it means

After resolving the Maps V2 controller, handleNewPoint looks up the points layer via mapsController.layerManager?.getLayer("points") and warns when it is not registered. The points layer only exists after the map controller has initialized its LayerManager and added the layer, so this means a realtime point arrived before the layer registry was populated (or the layer was removed). The incoming point is dropped.

Source

Thrown at app/javascript/controllers/maps/maplibre_realtime_controller.js:182

  }

  /**
   * Handle new point
   * Point data is broadcast as: [lat, lon, battery, altitude, timestamp, velocity, id, country_name]
   */
  handleNewPoint(pointData) {
    const mapsController = this.mapsV2Controller
    if (!mapsController) {
      console.warn("[Realtime Controller] Maps controller not found")
      return
    }

    const [lat, lon, battery, altitude, timestamp, velocity, id, countryName] =
      pointData

    const pointsLayer = mapsController.layerManager?.getLayer("points")
    if (!pointsLayer) {
      console.warn("[Realtime Controller] Points layer not found")
      return
    }

    const currentData = pointsLayer.data || {
      type: "FeatureCollection",
      features: [],
    }
    const features = [...(currentData.features || [])]

    features.push({
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [parseFloat(lon), parseFloat(lat)],
      },
      properties: {
        id: parseInt(id, 10),
        latitude: parseFloat(lat),

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Delay channel subscription until the map reports ready (subscribe from a map:ready callback/event instead of realtime controller connect()).
  2. Buffer incoming point features in the realtime controller while the layer is absent and flush them once getLayer("points") resolves.
  3. Verify the layer id registered in LayerManager for points is exactly "points" after any layer refactor.

Example fix

// before
const pointsLayer = mapsController.layerManager?.getLayer("points")
if (!pointsLayer) {
  console.warn("[Realtime Controller] Points layer not found")
  return
}

// after
const pointsLayer = mapsController.layerManager?.getLayer("points")
if (!pointsLayer) {
  this.pendingPoints = this.pendingPoints || []
  this.pendingPoints.push(pointData)
  return
}
Defensive patterns

Strategy: validation

Validate before calling

const layer = mapsController.layerManager?.getLayer("points")
if (!layer) { this.pendingPoints.push(pointData); return }

Prevention

When it happens

Trigger: An ActionCable new_point broadcast lands during page load before maplibre_controller.connect() has created and registered the points layer; or the points layer was hidden/removed (layer settings) while live mode is still subscribed; or the layer was registered under a different id than "points".

Common situations: Slow map init on mobile combined with immediate GPS uploads from a phone; Turbo navigation away from the map while the cable subscription briefly persists; toggling point-layer visibility off in settings then receiving live updates; refactoring layer ids in LayerManager.

Related errors


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