Freika/dawarich · warning

[Maps V2] Places layer not found, cannot update

Error message

[Maps V2] Places layer not found, cannot update

What it means

When a place creation event reaches the map, PlacesManager tries to upsert the saved place into the existing places layer (or reload the whole collection on first load). If LayerManager has no 'places' layer registered — layers not yet added, or already torn down — it logs this warning and skips, so the new place will not appear until a manual refresh.

Source

Thrown at app/javascript/controllers/maps/maplibre/places_manager.js:280

      )

      this.controller.map.getCanvas().style.cursor = ""
    }

    this.controller.map.once("click", this.handleCreatePlaceClick)
  }

  /**
   * Handle place creation/update events. The event carries the saved place,
   * so when the layer already holds data we upsert that single feature in
   * place instead of re-pulling the whole collection from the backend. A full
   * fetch happens only on first load, when the layer has no data yet.
   */
  async handlePlaceCreated(event) {
    try {
      const placesLayer = this.layerManager.getLayer("places")
      if (!placesLayer) {
        console.warn("[Maps V2] Places layer not found, cannot update")
        return
      }

      const place = event?.detail?.place
      if (place && placesLayer.data?.features?.length) {
        this._upsertPlaceFeature(placesLayer, place)
      } else {
        await this._reloadPlaces(placesLayer)
      }

      this._ensurePlacesVisible(placesLayer)
    } catch (error) {
      console.error("[Maps V2] Failed to update places:", error)
    }
  }

  /**
   * Handle place update event - same upsert path as creation.

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Confirm timing: if the event fires during map init, queue it and replay once addLayers completes
  2. Unsubscribe document-level listeners in the manager's disconnect/destroy so stale pages stop reacting
  3. Verify the layer id string matches what LayerManager registers ('places')
  4. If the layer is intentionally absent (feature off), downgrade to debug logging

Example fix

// before
const placesLayer = this.layerManager.getLayer("places")
if (!placesLayer) {
  console.warn("[Maps V2] Places layer not found, cannot update")
  return
}
// after
const placesLayer = this.layerManager.getLayer("places")
if (!placesLayer) {
  if (this.layersReady) console.warn("[Maps V2] Places layer not found, cannot update")
  else this.pendingPlaceEvents.push(event) // replay after layers initialize
  return
}
Defensive patterns

Strategy: type-guard

Validate before calling

const placesLayer = this.layerManager?.getLayer("places")
if (!placesLayer || typeof placesLayer.setData !== "function") {
  if (this.layersReady) console.warn("[Maps V2] Places layer not found, cannot update")
  else this.pendingPlaceEvents.push(event) // replay after addLayers
  return
}

Type guard

/** @param {unknown} layer @returns {boolean} */
function isPlacesLayer(layer) {
  return Boolean(
    layer &&
    typeof layer === "object" &&
    typeof layer.setData === "function" &&
    Array.isArray(layer.data?.features)
  )
}

Try / catch

try {
  await this._reloadPlaces(placesLayer)
} catch (error) {
  console.warn("[Maps V2] Places reload failed:", error)
}

Prevention

When it happens

Trigger: A place saved before the map finished initializing its layers; the document-level event firing after Turbo navigation tore the map down while the listener persisted; the places layer disabled or renamed in LayerManager; an event broadcast from another tab reaching a map instance whose places layer is absent.

Common situations: Multi-tab usage where events on the document object cross page boundaries; Turbo cache restores where managers outlive layers; races between initial data load and a quick place creation; layer id changes during Maps v2 refactors.

Related errors


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