MosaicLayer throws on every update after a source fails to load
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 75/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- computer-graphics, frontend
Research direction
Start in packages/deck.gl-geotiff/src/mosaic-layer/mosaic-layer.ts at the renderSubLayers logic referenced in the issue, and compare its handling of missing tile content with RasterTileLayer._renderSubLayers. Add or adapt a LayerManager test that rejects getSource, waits for the tile to settle, then updates again. Done means the update no longer throws and later loaded sources still draw.
Written by the indexing model from the issue text.
Description
[!NOTE]
This issue was written by Claude (Claude Code) on behalf of @kylebarron, not by @kylebarron.
Problem
When a source's getSource rejects, for example because its GeoTIFF returns 404, MosaicLayer breaks:
- Every later update of its inner
TileLayerthrowsTypeError: Cannot destructure property 'source' of 'data' as it is null. While the map pans, that's about one error per frame. - The
TileLayerstops drawing the sources that load after the failure.
Found in usgs-topo (kylebarron/usgs-topo#54). One sheet in a view of Twin Lakes, CA, is in the USGS catalog but not in its bucket. In headless Chrome, that view logged 334 errors over 12 short drags, and none of the 7.5' sheets in that MosaicLayer drew.
Seen with deck.gl-raster 0.9.0 and deck.gl 9.4.0. main (4b03f23) has the same code.
Cause
- deck.gl settles a tile whose
getTileDatarejected: it setscontenttonull, marks the tile loaded, and callsonError(tile-2d-header.ts#L150-L170). Its comment says this is on purpose, and deck.gl 9.1 and 9.2 do the same. TileLayer._onTileErrorclearstile.layersand asks for an update (tile-layer.ts#L333-L338).renderLayersthen callsrenderSubLayersfor the loaded tile withdata: tile.content, which isnull(#L411-L429).MosaicLayer'srenderSubLayersdestructuresprops.datawithout a check (mosaic-layer.ts#L286-L290). TypeScript doesn't flag it, because deck.gl types thatdataasDataT, notDataT | null(tile-layer.ts#L71-L78).
The throw comes before renderLayers sets tile.layers, so every later update renders that tile again and throws again. And since renderLayers throws, CompositeLayer._postUpdate never stores the new sublayers (composite-layer.ts#L252-L260). The TileLayer keeps drawing the sublayers of its last good render, which lack the sources that loaded since.
Both effects last as long as the failed tile stays in the tileset's cache. renderLayers walks every cached tile, not only the visible ones (tile-layer.ts#L408, tileset-2d.ts#L616). With the default maxCacheSize, five times the selected tiles (#L591-L594), a failed tile can stay cached long after it leaves the view.
RasterTileLayer._renderSubLayers already handles a tile without content (raster-tile-layer.ts#L546-L548).
Workaround
Make getSource resolve instead of reject, for example to null, and draw nothing for that data in renderSource. usgs-topo does this in kylebarron/usgs-topo#54.
Proposed fix
-
Return nothing for a tile without content:
renderSubLayers: (props) => { // A tile whose `getSource` rejected settles with `null` content. if (!props.data) { return null; } const { source, signal, data: userData } = props.data; return renderSource(source, { data: userData, signal }); },The failure is still reported once per load: through
onSourceErrorif it's set, and otherwise byTileLayer's defaultonTileError, which logs it. -
Test it: render a
MosaicLayerwhosegetSourcerejects through aLayerManager, with a viewport over the source. Wait for the tile to settle, then update again. usgs-topo has a test like this (cog-mosaic-open.test.ts#L97-L129).
🤖 Written by Claude Code
- Dominant language
- TypeScript
- Stars
- 231
- Forks
- 34
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 71
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from developmentseed/deck.gl-raster
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
developmentseed/deck.gl-raster#589 ·
Maintainers usually reply within 1 day
-
Add zarr-globe examplePossibly taken @kylebarron claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
developmentseed/deck.gl-raster#568 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
developmentseed/deck.gl-raster#803 ·
Maintainers usually reply within 1 day
-
cog
Difficulty 3/5 1-2 days Newbie friendliness 68/100
developmentseed/deck.gl-raster#800 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 58/100
developmentseed/deck.gl-raster#797 ·
Maintainers usually reply within 1 day
All issues in developmentseed/deck.gl-raster
Similar issues
-
Plugin: sheet music can't be scrolled by hand before playbackPossibly taken @snakajima claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
receptron/jinglescript#51 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 9 days
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
openclaw/openclaw#186424 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
chore(worker): five module header comments describe the code from before later issues changed itOpenarea:dev U2-later
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
bentleypark/aiwatch#1824 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Pal-AI-Lab/Coopanion#469 ·
Maintainers usually reply within 1 day