{"record":{"id":"bc22ab1910bc4856","repo":"Freika/dawarich","slug":"mapinitializer-no-features-to-fit-bounds-to","errorCode":null,"errorMessage":"[MapInitializer] No features to fit bounds to","messagePattern":"\\[MapInitializer\\] No features to fit bounds to","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"app/javascript/controllers/maps/maplibre/map_initializer.js","lineNumber":141,"sourceCode":"    map.addControl(\n      new maplibregl.AttributionControl({ compact: true }),\n      \"bottom-right\",\n    )\n\n    return map\n  }\n\n  /**\n   * Fit map to bounds of GeoJSON features\n   * @param {maplibregl.Map} map - The map instance\n   * @param {Object} geojson - GeoJSON FeatureCollection\n   * @param {Object} options - Fit bounds options\n   */\n  static fitToBounds(map, geojson, options = {}) {\n    const { padding = 50, maxZoom = 15 } = options\n\n    if (!geojson?.features?.length) {\n      console.warn(\"[MapInitializer] No features to fit bounds to\")\n      return\n    }\n\n    const coordinates = geojson.features.map((f) => f.geometry.coordinates)\n\n    const bounds = coordinates.reduce((bounds, coord) => {\n      return bounds.extend(coord)\n    }, new maplibregl.LngLatBounds(coordinates[0], coordinates[0]))\n\n    map.fitBounds(bounds, {\n      padding,\n      maxZoom,\n    })\n  }\n}\n","sourceCodeStart":123,"sourceCodeEnd":157,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/controllers/maps/maplibre/map_initializer.js#L123-L157","documentation":"A guard, not a failure: MapInitializer.fitToBounds refuses to build an LngLatBounds and call map.fitBounds when the supplied FeatureCollection has zero features, because fitting bounds to nothing is undefined (MapLibre would throw or zoom the world). The warning marks the skip so developers understand why the map kept its previous view.","triggerScenarios":"A brand-new account with no points yet; date-range, viewport, or layer filters excluding every feature; the API returning an empty FeatureCollection before the first import completes; fitToBounds called during teardown with already-cleared data.","commonSituations":"Fresh self-hosted installs before the first Owntracks/Overland import; filters narrower than the tracked data; demo instances with empty seeds; an upstream auth failure silently degrading to an empty collection.","solutions":["Confirm the empty set is expected (new account or heavy filters) — nothing is broken","When empty, provide a sensible default view instead of keeping a stale one","If data should exist, check the upstream fetch — an auth failure can degrade to an empty collection","Downgrade to console.debug in production to reduce noise"],"exampleFix":"// before\nif (!geojson?.features?.length) {\n  console.warn(\"[MapInitializer] No features to fit bounds to\")\n  return\n}\n// after\nif (!geojson?.features?.length) {\n  console.debug(\"[MapInitializer] No features to fit bounds to\")\n  map.jumpTo({ center: [0, 0], zoom: 2 }) // deterministic default view\n  return\n}","handlingStrategy":"validation","validationCode":"const hasFeatures =\n  Array.isArray(geojson?.features) &&\n  geojson.features.length > 0 &&\n  geojson.features.some((f) => f?.geometry?.coordinates)\nif (!hasFeatures) {\n  map.jumpTo({ center: DEFAULT_CENTER, zoom: DEFAULT_ZOOM })\n  return\n}","typeGuard":"/** @param {unknown} gj @returns {boolean} */\nfunction isNonEmptyFeatureCollection(gj) {\n  return Boolean(\n    gj &&\n    typeof gj === \"object\" &&\n    Array.isArray(gj.features) &&\n    gj.features.length > 0\n  )\n}","tryCatchPattern":null,"preventionTips":["Check features.length before any fitBounds call — MapLibre cannot fit an empty bounds","Always supply a default center/zoom for the empty case","Distinguish 'empty because of filters' from 'empty because the fetch failed' before fitting"],"tags":["maplibre","fitbounds","geojson","guard","empty-data"],"backgroundTag":"empty-geojson-feature-collection","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}