{"record":{"id":"6033209b84e08d90","repo":"Freika/dawarich","slug":"maps-v2-places-layer-not-found-cannot-update","errorCode":null,"errorMessage":"[Maps V2] Places layer not found, cannot update","messagePattern":"\\[Maps V2\\] Places layer not found, cannot update","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/javascript/controllers/maps/maplibre/places_manager.js","lineNumber":280,"sourceCode":"      )\n\n      this.controller.map.getCanvas().style.cursor = \"\"\n    }\n\n    this.controller.map.once(\"click\", this.handleCreatePlaceClick)\n  }\n\n  /**\n   * Handle place creation/update events. The event carries the saved place,\n   * so when the layer already holds data we upsert that single feature in\n   * place instead of re-pulling the whole collection from the backend. A full\n   * fetch happens only on first load, when the layer has no data yet.\n   */\n  async handlePlaceCreated(event) {\n    try {\n      const placesLayer = this.layerManager.getLayer(\"places\")\n      if (!placesLayer) {\n        console.warn(\"[Maps V2] Places layer not found, cannot update\")\n        return\n      }\n\n      const place = event?.detail?.place\n      if (place && placesLayer.data?.features?.length) {\n        this._upsertPlaceFeature(placesLayer, place)\n      } else {\n        await this._reloadPlaces(placesLayer)\n      }\n\n      this._ensurePlacesVisible(placesLayer)\n    } catch (error) {\n      console.error(\"[Maps V2] Failed to update places:\", error)\n    }\n  }\n\n  /**\n   * Handle place update event - same upsert path as creation.","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/controllers/maps/maplibre/places_manager.js#L262-L298","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm timing: if the event fires during map init, queue it and replay once addLayers completes","Unsubscribe document-level listeners in the manager's disconnect/destroy so stale pages stop reacting","Verify the layer id string matches what LayerManager registers ('places')","If the layer is intentionally absent (feature off), downgrade to debug logging"],"exampleFix":"// before\nconst placesLayer = this.layerManager.getLayer(\"places\")\nif (!placesLayer) {\n  console.warn(\"[Maps V2] Places layer not found, cannot update\")\n  return\n}\n// after\nconst placesLayer = this.layerManager.getLayer(\"places\")\nif (!placesLayer) {\n  if (this.layersReady) console.warn(\"[Maps V2] Places layer not found, cannot update\")\n  else this.pendingPlaceEvents.push(event) // replay after layers initialize\n  return\n}","handlingStrategy":"type-guard","validationCode":"const placesLayer = this.layerManager?.getLayer(\"places\")\nif (!placesLayer || typeof placesLayer.setData !== \"function\") {\n  if (this.layersReady) console.warn(\"[Maps V2] Places layer not found, cannot update\")\n  else this.pendingPlaceEvents.push(event) // replay after addLayers\n  return\n}","typeGuard":"/** @param {unknown} layer @returns {boolean} */\nfunction isPlacesLayer(layer) {\n  return Boolean(\n    layer &&\n    typeof layer === \"object\" &&\n    typeof layer.setData === \"function\" &&\n    Array.isArray(layer.data?.features)\n  )\n}","tryCatchPattern":"try {\n  await this._reloadPlaces(placesLayer)\n} catch (error) {\n  console.warn(\"[Maps V2] Places reload failed:\", error)\n}","preventionTips":["Bind document-level place events only after layers finish initializing; unbind on disconnect","Queue early events and replay them once the layer exists","Keep layer id constants in one module so registrations and lookups cannot drift"],"tags":["dawarich","places-layer","event-race","stimulus","turbo"],"backgroundTag":"map-layer-not-found","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}