{"record":{"id":"ed7bb8e2b578f849","repo":"Freika/dawarich","slug":"failed-to-load-scratch-layer","errorCode":null,"errorMessage":"Failed to load scratch layer:","messagePattern":"Failed to load scratch layer:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/javascript/controllers/maps/maplibre/layer_manager.js","lineNumber":297,"sourceCode":"    )\n  }\n\n  // Private methods for individual layer management\n\n  async _addScratchLayer(pointsGeoJSON) {\n    try {\n      if (!this.layers.scratchLayer && this.settings.scratchEnabled) {\n        const ScratchLayer = await lazyLoader.loadLayer(\"scratch\")\n        this.layers.scratchLayer = new ScratchLayer(this.map, {\n          visible: true,\n          apiClient: this.api,\n        })\n        await this.layers.scratchLayer.add(pointsGeoJSON)\n      } else if (this.layers.scratchLayer) {\n        await this.layers.scratchLayer.update(pointsGeoJSON)\n      }\n    } catch (error) {\n      console.warn(\"Failed to load scratch layer:\", error)\n    }\n  }\n\n  _addHeatmapLayer(pointsGeoJSON) {\n    if (!this.layers.heatmapLayer) {\n      this.layers.heatmapLayer = new HeatmapLayer(this.map, {\n        visible:\n          this.settings.heatmapEnabled &&\n          !tiledPointsActive(SettingsManager.getSettings()),\n      })\n      this.layers.heatmapLayer.add(pointsGeoJSON)\n    } else {\n      this.layers.heatmapLayer.update(pointsGeoJSON)\n    }\n  }\n\n  _addHexagonLayer() {\n    if (this.layers.hexagonsLayer) return this.layers.hexagonsLayer","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/controllers/maps/maplibre/layer_manager.js#L279-L315","documentation":"The scratch layer (freehand drawing on the map) is code-split and loaded on demand through lazyLoader.loadLayer('scratch') when settings.scratchEnabled is on. This warning means the dynamic import or the layer's constructor/add() threw: most often a chunk load error after a new deploy invalidated old asset hashes, otherwise a runtime bug in the ScratchLayer module itself.","triggerScenarios":"A long-lived tab loading the scratch chunk after a deploy renamed chunk files (ChunkLoadError); a Vite/bundler misconfiguration dropping the scratch chunk from the build; an exception inside new ScratchLayer(...) or scratchLayer.add(pointsGeoJSON); scratchEnabled turned on on a build that lacks the layer code.","commonSituations":"Deploying while users have the map open; stale service-worker or CDN caches serving mixed asset versions; feature flag enabled before the code shipped; partial local builds during development.","solutions":["Hard-reload the page (Cmd/Ctrl+Shift+R) — stale chunk references after a deploy are the most common cause","Verify the scratch chunk exists in the current build output and matches the asset manifest","If the chunk loads but still throws, reproduce with the error object expanded to find the failing line in ScratchLayer","If the feature is not ready, disable scratchEnabled in settings until the build is fixed"],"exampleFix":"// before\nconst ScratchLayer = await lazyLoader.loadLayer(\"scratch\")\n// after\nlet ScratchLayer\ntry {\n  ScratchLayer = await lazyLoader.loadLayer(\"scratch\")\n} catch (e) {\n  if (String(e?.name).includes(\"ChunkLoadError\")) {\n    window.location.reload() // pick up freshly deployed chunk names\n    return\n  }\n  throw e\n}","handlingStrategy":"retry","validationCode":"if (!this.settings.scratchEnabled) return // never import when the feature is off","typeGuard":null,"tryCatchPattern":"try {\n  const ScratchLayer = await lazyLoader.loadLayer(\"scratch\")\n  this.layers.scratchLayer = new ScratchLayer(this.map, { visible: true, apiClient: this.api })\n  await this.layers.scratchLayer.add(pointsGeoJSON)\n} catch (error) {\n  if (String(error?.name).includes(\"ChunkLoadError\")) {\n    window.location.reload() // one reload picks up new chunk hashes after a deploy\n    return\n  }\n  console.warn(\"Failed to load scratch layer:\", error)\n}","preventionTips":["Prompt a reload when lazy chunks 404 after a deploy instead of silently dropping the feature","Gate optional layers behind their settings flag so the import is never attempted unnecessarily","Keep lazy-loaded modules self-contained so their absence degrades only their own feature"],"tags":["dawarich","scratch-layer","dynamic-import","chunk-load","vite"],"backgroundTag":"chunk-load-error","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}