Freika/dawarich · warning
Failed to add photos layer:
Error message
Failed to add photos layer:
What it means
LayerManager.addLayers() adds every layer synchronously except photos, which is awaited inside a try/catch because loading photo images is async and can fail. If _addPhotosLayer throws (broken image URLs, EXIF/decode failures, malformed GeoJSON), the warning is logged and the remaining layers (family, anomalies, points, routes hit, recent point, replay, fog) are still added — only photo markers go missing.
Source
Thrown at app/javascript/controllers/maps/maplibre/layer_manager.js:76
// Layer order matters - layers added first render below layers added later
// Order: scratch (bottom) -> heatmap -> areas -> tracks -> routes (visual) -> visits -> places -> photos -> family -> points -> routes-hit (interaction) -> recent-point (top) -> fog (canvas overlay)
// Note: routes-hit is above points visually but points dragging takes precedence via event ordering
await this._addScratchLayer(pointsGeoJSON)
this._addHeatmapLayer(pointsGeoJSON)
this._addHexagonLayer()
this._addAreasLayer(areasGeoJSON)
this._addTracksLayer(tracksGeoJSON)
this._addRoutesLayer(routesGeoJSON)
this._addFlightsLayer(flightsGeoJSON)
this._addVisitsLayer(visitsGeoJSON)
this._addPlacesLayer(placesGeoJSON)
// Add photos layer with error handling (async, might fail loading images)
try {
await this._addPhotosLayer(photosGeoJSON)
} catch (error) {
console.warn("Failed to add photos layer:", error)
}
this._addFamilyLayer()
this._addAnomaliesLayer()
this._addPointsMvtLayer()
this._addPointsLayer(pointsGeoJSON)
this._addRoutesHitLayer() // Add hit target layer after points, will be on top visually
this._addRecentPointLayer()
this._addReplayMarkerLayer()
this._addFogLayer(pointsGeoJSON)
performanceMonitor.measure("add-layers")
}
/**
* Setup event handlers for layer interactions
* Only sets up handlers once to prevent duplicates
*/View on GitHub (pinned to 97fad417c5)
Solutions
- Expand the logged error object — it distinguishes URL fetch failures from decode/EXIF failures
- Open the photos API endpoint in a browser and confirm every URL in the GeoJSON resolves (watch for 403/404 from storage)
- Fix or remove the single bad photo record, then reload — often one broken image aborts the entire batch
- If images are external, ensure CORS or proxy headers allow the map origin
Example fix
// before
try {
await this._addPhotosLayer(photosGeoJSON)
} catch (error) {
console.warn("Failed to add photos layer:", error)
}
// after
try {
await this._addPhotosLayer(photosGeoJSON)
} catch (error) {
console.warn("Failed to add photos layer:", error)
// Degrade per-photo so one broken image cannot blank the whole layer
this._addPhotosLayer(photosGeoJSON, { skipFailingImages: true }).catch(() => {})
} Defensive patterns
Strategy: try-catch
Validate before calling
const validPhotos = {
type: "FeatureCollection",
features: (photosGeoJSON?.features || []).filter(
(f) =>
f?.geometry &&
typeof f.properties?.image_url === "string" &&
f.properties.image_url.length > 0
),
}
await this._addPhotosLayer(validPhotos) Try / catch
try {
await this._addPhotosLayer(photosGeoJSON)
} catch (error) {
console.warn("Failed to add photos layer:", error)
// Photos are non-critical: continue adding the remaining layers
} Prevention
- Validate photo feature URLs before they reach the layer
- Isolate async image loading per photo so one failure cannot reject the whole layer add
- Keep the photos layer behind the same feature flag as photo import so users without photos skip it entirely
When it happens
Trigger: photosGeoJSON containing features with broken or expired image URLs; a photo whose EXIF parsing or image decode fails inside the photos layer; malformed photos GeoJSON (missing geometry or properties); object storage/CDN unreachable so image prefetch rejects.
Common situations: Self-hosted Dawarich with S3/MinIO storage misconfigured (wrong or unsigned URLs); photos synced from Immich or GPX imports with stale URLs; reverse proxy blocking image content types; a single corrupt photo aborting the whole batch.
Related errors
- [EventHandlers] Failed to highlight track:
- Failed to parse track segments:
- Failed to apply speed colors to route:
- [MapInitializer] No features to fit bounds to
- Failed to fetch points: ${response.statusText}
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/411abd091ae918af.
Report an issue: GitHub.