{"record":{"id":"083f9c301ee2f7c3","repo":"Freika/dawarich","slug":"failed-to-parse-track-segments-for-marker-update","errorCode":null,"errorMessage":"Failed to parse track segments for marker update:","messagePattern":"Failed to parse track segments for marker update:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/javascript/controllers/maps/maplibre/event_handlers.js","lineNumber":1093,"sourceCode":"   * Update track segment markers when track geometry changes\n   * Called after track recalculation to move emoji markers to new positions\n   * @param {Object} feature - The updated track GeoJSON feature\n   */\n  updateTrackMarkers(feature) {\n    if (!this.selectedTrackFeature) return\n    if (!feature || !feature.geometry || feature.geometry.type !== \"LineString\")\n      return\n\n    // Parse segments from feature properties\n    let segments = []\n    try {\n      const props = feature.properties || {}\n      segments =\n        typeof props.segments === \"string\"\n          ? JSON.parse(props.segments)\n          : props.segments || []\n    } catch (err) {\n      console.warn(\"Failed to parse track segments for marker update:\", err)\n      return\n    }\n\n    const trackId = feature.properties?.id\n    this._createTrackSegmentMarkers(trackId, feature, segments)\n  }\n\n  /**\n   * Zoom the map to fit a specific segment's bounds\n   * @param {Object} segment - Segment data with start_index and end_index\n   */\n  _zoomToSegment(segment) {\n    if (!this.selectedTrackFeature || !segment) return\n\n    const coords = this.selectedTrackFeature.geometry?.coordinates\n    if (!coords || coords.length < 2) return\n\n    const startIdx = Math.max(0, segment.start_index || 0)","sourceCodeStart":1075,"sourceCodeEnd":1111,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/controllers/maps/maplibre/event_handlers.js#L1075-L1111","documentation":"The track-segment marker update path reads feature.properties.segments the same way as the click path: a string value is passed to JSON.parse, and a malformed string throws. Unlike the click path, this handler returns early on failure, so segment markers are not created at all for that track.","triggerScenarios":"A track feature whose segments property is an invalid JSON string (truncated response, double encoding, NaN in the payload); features built by hand or cached from an older API version; marker refresh triggered by a live track update that carries a partial payload.","commonSituations":"Marker updates after live track pushes with incomplete data; switching between tiled and non-tiled point sources; stale caches from an upgraded backend; tracks imported by older importers that produced malformed segment JSON.","solutions":["Inspect the failing feature's properties.segments in the debugger to find the exact JSON syntax error","Fix the producing serializer or importer to emit valid segment JSON","Share one safe-parse helper between the click path and the marker path so both degrade identically","If markers matter for this track, fall back to re-fetching via fetchTrackWithSegments instead of returning silently"],"exampleFix":"// before\ntry {\n  const props = feature.properties || {}\n  segments =\n    typeof props.segments === \"string\"\n      ? JSON.parse(props.segments)\n      : props.segments || []\n} catch (err) {\n  console.warn(\"Failed to parse track segments for marker update:\", err)\n  return\n}\n// after\nconst props = feature.properties || {}\nconst segments = safeParseSegments(props.segments) // shared helper, never throws\nif (!segments.length) return\nthis._createTrackSegmentMarkers(trackId, feature, segments)","handlingStrategy":"validation","validationCode":"const raw = feature.properties?.segments\nconst looksParsable =\n  Array.isArray(raw) ||\n  (typeof raw === \"string\" && raw.trimStart().startsWith(\"[\"))\nif (!looksParsable) return // avoid JSON.parse on obviously wrong payloads","typeGuard":"/** @param {unknown} raw @returns {boolean} */\nfunction isParsableSegments(raw) {\n  if (Array.isArray(raw)) return true\n  if (typeof raw !== \"string\") return false\n  const t = raw.trim()\n  return t.startsWith(\"[\") && t.endsWith(\"]\")\n}","tryCatchPattern":"try {\n  segments = safeParseSegments(props.segments)\n} catch (err) {\n  console.warn(\"Failed to parse track segments for marker update:\", err)\n  return // skip markers for this track only; do not break the surrounding loop\n}","preventionTips":["Validate payloads at the API boundary once, not in every consumer","Keep a single shared safe-parse utility for segments used by click, hover, and marker paths","Log the track id alongside the warning so bad data can be traced to a specific record"],"tags":["json-parse","dawarich","track-segments","markers"],"backgroundTag":"json-parse-error","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}