bluerobotics / bluerobotics/cockpit

Offline tiles downloaded before v1.19.0-beta.1 are silently ignored (cache key includes the full tile URL)

Open
#2,887 0 comments 0 reactions 0 assignees View on GitHub
map
Dominant language
TypeScript
Stars
198
Forks
63
Avg merge
2d 7h
Merged PRs (30d)
57

Description

## Problem

A user downloaded offline map tiles ahead of a mission and found them missing in the field. The tiles are still in IndexedDB — they are just no longer reachable.

## Cause

`leaflet.offline` keys each stored tile by its fully resolved URL, built from the layer's URL template (`node_modules/leaflet.offline/src/TileLayerOffline.ts`):

```ts
_getStorageKey(coords) {
return getTileUrl(this._url, { ...coords, ...this.options, s: this.options.subdomains['0'] });
}
```

So any change to a provider's URL template invalidates every tile previously downloaded from it. That happened in 856b29c9b3 ("map: integrate procedural-noise fallback into base maps", first released in `v1.19.0-beta.1`), which appended a query parameter to the Esri World Imagery template:

```diff
-'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
+'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}?blankTile=false',
```

The parameter is needed for the network request (it makes ArcGIS return 404 instead of a placeholder image, which drives the noise fallback), but it does not need to be part of the storage key. Every satellite tile downloaded on <= 1.18 became a cache miss on update, with no warning and no way to tell from the UI.

## Suggested fix

Normalize the storage key so it ignores the query string, and fall back to the legacy key on lookup so tiles already downloaded under either scheme keep working. Provider URL tweaks should not be able to strand a user's downloads.

## Related, same symptom

Which base layer the map opens on, and where, is profile-scoped: `cockpit-user-last-map-tile-provider`, `cockpit-user-last-map-center` and `cockpit-user-last-map-zoom` are all `useBlueOsStorage` keys read once at setup (`src/components/widgets/Map.vue:302-303`, `src/composables/map/useMapTileLayerSelection.ts:45-51`). Connecting to a different vehicle can therefore bring the map up on a layer or an area that was never downloaded, which is indistinguishable from a lost cache. The tile cache itself is not profile-scoped and is never wiped by a profile switch.

Worth considering whether the map should indicate that the current view has no cached coverage, rather than showing empty tiles.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in node_modules/leaflet.offline/src/TileLayerOffline.ts and trace how tile storage keys are generated and looked up. Check the map setup references in src/components/widgets/Map.vue:302-303 and src/composables/map/useMapTileLayerSelection.ts:45-51 to understand the related profile-scoped state. Done means tiles downloaded with both the current and legacy URL forms remain reachable after provider URL changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.