Say so when a COG's tiles can't be drawn - #161
Merged
Merged
Conversation
Every other preview reports a failure through <ogm-preview>'s alert. A COG drawn by deck.gl had one path there - a file that refused to be opened, which rejects preview() - and nothing for the failures that arrive after that. Tiles come in one at a time, and deck.gl reports one that couldn't be built by calling onTileError rather than by rejecting anything. Left unhandled, its own handler logs the tile and the map stays empty: a record zoomed to the right place with no layer on it and no reason given. That is what #158 looks like from the outside. The COG in it is stored band- separate, which the version of @developmentseed/deck.gl-geotiff we build against refuses outright, so every tile of it fails the same way. The fix for that file is upstream (developmentseed/deck.gl-raster#635); this is about the viewer having nothing to say when a COG can't be drawn, whatever the reason. MapPreviewer gains an onError, which is where a failure that arrives after preview() has resolved goes. Nothing MapLibre draws needs it - it fires those on the map itself, and <ogm-map> has listened to that since alerts existed - so this is for the previews that paint with their own WebGL and have no such channel. <ogm-map> binds it to the same reportError() a failed load takes, which already dedupes to one alert per load attempt, so a viewport's worth of failing tiles reports once rather than forty times. It is bound to the previewer it came from rather than to whichever is current, because a tile of the record the user just left would otherwise report against the one that replaced it. Only the first failure of a COG that has drawn nothing reaches that alert. A COG can be sparse by design, and the alert covers the map completely - so a tile that failed among tiles that didn't would replace a preview the user can see with an error about a hole in it. Those are logged and left alone. Aborted reads are dropped rather than logged: deck.gl discards a cancelled tile before calling back, so a pan that abandons its reads doesn't arrive here at all, but a decoder that notices the abort itself can still throw one. The message the user sees is deck.gl's own, through referenceError, which is cryptic for the band-separate case in particular. Naming it here would mean matching on an upstream string that the upstream fix removes, so it stays as it is. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every other preview reports a failure through
<ogm-preview>'s alert. A COG drawn by deck.gl had one path there — a file that refused to be opened, which rejectspreview()— and nothing for the failures that arrive after that. Tiles come in one at a time, and deck.gl reports one it couldn't build by callingonTileErrorrather than by rejecting anything. Left unhandled, its own handler logs the tile and the map stays empty: a record zoomed to the right place with no layer on it and no reason given.That's what #158 looks like from the outside. Diagnosis of the file in that issue, for the record:
ColorInterp=Alpha,ExtraSamples=2BAND/PlanarConfiguration=2← the triggerTransparency isn't the problem; interleaving is.
@developmentseed/deck.gl-geotiffthrowsBand-separate images not yet implemented.for that layout, so every tile fails the same way. The fix for that file is upstream — developmentseed/deck.gl-raster#635, open and green. This PR is the other half: the viewer having something to say when a COG can't be drawn, whatever the reason.What changed
MapPreviewer.onError— where a failure that arrives afterpreview()has resolved goes. Nothing MapLibre draws needs it; it fires those on the map itself, which<ogm-map>has listened to since alerts existed. This is for the previews that paint with their own WebGL and have no such channel.<ogm-map>binds it to the samereportError()a failed load takes, so a viewport's worth of failing tiles produces one alert rather than forty — that dedupe already existed. Bound to the previewer it came from rather than to whichever is current, so a tile of the record the user just left can't report against the one that replaced it.DeckCogPreviewertakesonTileErrorandonTileLoad.Two judgement calls
Only the first failure of a COG that has drawn nothing reaches the alert. A COG can be sparse by design, and the alert covers the map completely — so a tile that failed among tiles that didn't would replace a working preview with an error about a hole in it. Those are logged and left alone. Without this the change would be a regression for sparse COGs.
Aborted reads are dropped. deck.gl discards a cancelled tile before calling back, so a pan that abandons its reads never arrives here; but a decoder that notices the abort itself can still throw one, and that isn't a failed preview.
What the user sees
The message is deck.gl's own, through
referenceError:Cryptic for this case in particular. Translating it would mean matching on an upstream string that developmentseed/deck.gl-raster#635 deletes, so it stays as it is — happy to add a mapping in
errors.tsif you'd rather.Testing
Four cases in
cog-deck.test.tscovering all of the above: reports when nothing has drawn, stays quiet once some of the COG is on screen, ignores anAbortError, and reports again after a second load attempt. Full suite green (612 unit, 98 component) andnpm run lintclean.Checked in the browser against the record from #158 — one alert, not one per tile — and against the Tibet COG, which still draws with no alert and clears the previous one.
Note that #158 stays open until the upstream fix ships and we bump
@developmentseed/deck.gl-geotiffand@developmentseed/geotiff(we're on 0.7.0; that PR targets 0.8.0-beta.2, so expect other API changes in the bump).🤖 Generated with Claude Code