fix(mapbox): guard against null viewport when canvas has zero dimensions#10076
fix(mapbox): guard against null viewport when canvas has zero dimensions#10076Pessimistress merged 12 commits intomasterfrom
Conversation
Modify the mock Map._render() to catch errors from style.render() and
store them as _renderError, then always fire the render event so tests
don't hang silently.
Add t.notOk(_renderError) assertions in the map.on('render', ...) handlers
of the two multi-view tests so the null-viewport bug is surfaced as an
explicit test failure rather than a silent hang.
https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
| this.style.render(); | ||
| } catch (e) { | ||
| this._renderError = e; | ||
| } |
There was a problem hiding this comment.
Stale _renderError never cleared between render calls
Low Severity
_renderError is only ever assigned on failure and never reset to null/undefined at the start of _render(). If _render() is called multiple times (e.g., via multiple triggerRepaint() calls queued by Deck's _customRender), an error from an earlier render persists even if a later render succeeds. The t.notOk(_renderError) assertion in the render handler would then report a stale error, producing a misleading or false test failure. Adding this._renderError = null before the try-catch would ensure the value always reflects the most recent render attempt.
makeViewport() returns null when deck.width or deck.height is 0 (e.g. when the map container is hidden or detached). drawLayer and drawLayerGroup now return early in that case instead of passing null into deck._drawLayers, which would throw. Add a test that forces deck.width/height to 0 before firing a render to reproduce and verify the fix. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
Reverts the fix from the previous commit so the new zero-size canvas test can be seen failing before the fix is applied. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
…e test
map.fire('render') bypasses style.render() so drawLayer was never called.
_render() goes through the full path: style.render() -> layer.render()
-> drawLayer(), which is where the null viewport crash occurs.
https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
drawLayer returns early when !deck.isInitialized, so calling _render() synchronously after construction never hit the crash path. Move the zero-dimensions setup and _render() call into the deck's onLoad callback (which getDeckInstance wraps but still calls). By that point deck.isInitialized is true, so drawLayer proceeds and the null-viewport crash is exercised. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
makeViewport() returns null when deck.width or deck.height is 0 (e.g. when the map container is hidden or detached). drawLayer and drawLayerGroup now return early in that case instead of passing null into deck._drawLayers, which would throw. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
afterRender also calls getViewport() and was inserting the result directly into the viewports array without a null check. When the canvas has zero dimensions, getViewport returns null, causing deck._drawLayers to crash for any deck that has non-Mapbox layers or non-Mapbox views. Add an early return in afterRender when the viewport is null, and a regression test that exercises this path (layer not registered as a MapboxLayer so afterRender's hasNonMapboxLayers branch is taken). https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
Reverts the fix so the new afterRender zero-size canvas test can be seen failing in CI before the fix is applied. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
The previous version used an unregistered layer (hasNonMapboxLayers), which is unreachable through MapboxOverlay since resolveLayers registers every deck layer as a MapboxLayer. The real public API path is hasNonMapboxViews — triggered when the user passes multiple views. Rewrite the test to use two views so it exercises the actual code path that hits getViewport in afterRender. https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo


Fixes issue observed in #10075
When a Mapbox/MapLibre map container is hidden or detached, the deck.gl canvas can have zero width or height.
In that case,
view.makeViewport()returnsnull, anddrawLayer/drawLayerGroupwere passing thatnulldirectly intodeck._drawLayers()as the viewport, causing a crash.The fix adds an early return in both
drawLayeranddrawLayerGroupwhen the viewport isnull.A regression test was added that forces
deck.widthanddeck.heightto zero before triggering a render, verifying no error is thrown.https://claude.ai/code/session_01QMHj3ie96cqTLwVYxWwSXo
Note
Low Risk
Low risk defensive change in Mapbox rendering: it only short-circuits drawing when
getViewport()returnsnull, preventing a crash when the canvas has 0×0 dimensions.Overview
Prevents crashes in Mapbox/MapLibre integration when the deck.gl canvas is hidden/detached (0×0), by early-returning in
drawLayeranddrawLayerGroupwhengetViewport()returnsnullinstead of passing a null viewport intodeck._drawLayers().Tests were hardened to surface render exceptions (mock map captures
_renderError), and new regression specs cover bothMapboxLayer#drawLayerand theafterRenderpath under a zero-size canvas to ensure renders do not throw.Written by Cursor Bugbot for commit 97cecef. This will update automatically on new commits. Configure here.