Freika/dawarich · warning

[Realtime Controller] Maps controller not found

Error message

[Realtime Controller] Maps controller not found

What it means

The realtime controller resolves the Maps V2 controller via application.getControllerForElementAndIdentifier(this.element, "maps--maplibre"), which returns null unless the realtime controller's element is the same element as, or a descendant of, the element carrying data-controller="maps--maplibre". When an ActionCable "new_point" broadcast arrives and that lookup fails, the handler bails with this warning. It is a Stimulus controller-wiring/DOM-nesting problem, not a cable problem.

Source

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

  }

  /**
   * Get the maps--maplibre controller (on same element)
   */
  get mapsV2Controller() {
    const element = this.element
    const app = this.application
    return app.getControllerForElementAndIdentifier(element, "maps--maplibre")
  }

  /**
   * 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 || [])]

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Nest the realtime controller element inside the element with data-controller="maps--maplibre" so getControllerForElementAndIdentifier can find it.
  2. Defer channel subscription until the map controller signals readiness (e.g. subscribe on a custom map:ready event dispatched by maplibre_controller) so broadcasts cannot arrive before the controller exists.
  3. If the controller file was moved/renamed, verify the identifier passed matches the path-derived name maps--maplibre (directory maps/ + file maplibre_controller.js).

Example fix

// before
// <div data-controller="maps--maplibre-realtime"> ... </div>
// <div data-controller="maps--maplibre"> map canvas </div>

// after
// <div data-controller="maps--maplibre">
//   <div data-controller="maps--maplibre-realtime"> ... </div>
//   map canvas
// </div>
Defensive patterns

Strategy: validation

Validate before calling

const ctrl = this.application.getControllerForElementAndIdentifier(
  this.element,
  "maps--maplibre",
)
if (!ctrl) return // do not subscribe yet

Prevention

When it happens

Trigger: An ActionCable new_point broadcast for the user's points channel arrives while (a) the realtime controller element sits outside the maps--maplibre element's subtree, (b) the maplibre controller has not yet connected (map still initializing), or (c) the identifier string was changed (file rename maps/maplibre_controller.js changes the default identifier to maps--maplibre).

Common situations: Moving the live-mode toggle / realtime wrapper div outside the map container in views; Turbo frame or morphdom re-render that detaches the map element; a broadcast that lands during page load before Stimulus connect() completes; renaming the controller file or setting a custom static identifier.

Related errors


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