Skip to content

fix(mapbox): guard against null viewport when canvas has zero dimensions#10076

Merged
Pessimistress merged 12 commits intomasterfrom
claude/fix-mapbox-null-viewport-nsDGF
Mar 10, 2026
Merged

fix(mapbox): guard against null viewport when canvas has zero dimensions#10076
Pessimistress merged 12 commits intomasterfrom
claude/fix-mapbox-null-viewport-nsDGF

Conversation

@chrisgervang
Copy link
Copy Markdown
Collaborator

@chrisgervang chrisgervang commented Mar 8, 2026

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() returns null, and drawLayer/drawLayerGroup were passing that null directly into deck._drawLayers() as the viewport, causing a crash.
The fix adds an early return in both drawLayer and drawLayerGroup when the viewport is null.

A regression test was added that forces deck.width and deck.height to 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() returns null, 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 drawLayer and drawLayerGroup when getViewport() returns null instead of passing a null viewport into deck._drawLayers().

Tests were hardened to surface render exceptions (mock map captures _renderError), and new regression specs cover both MapboxLayer#drawLayer and the afterRender path 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.

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;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

@coveralls
Copy link
Copy Markdown

coveralls commented Mar 8, 2026

Coverage Status

coverage: 91.003% (-0.002%) from 91.005%
when pulling b03d72e on claude/fix-mapbox-null-viewport-nsDGF
into 01f071e on master.

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
claude added 5 commits March 8, 2026 23:42
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
@chrisgervang chrisgervang changed the title test(mapbox): expose null-viewport crash in drawLayer/drawLayerGroup fix(mapbox): guard against null viewport when canvas has zero dimensions Mar 9, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

claude and others added 4 commits March 9, 2026 16:33
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
@Pessimistress Pessimistress merged commit 334eb8b into master Mar 10, 2026
3 of 4 checks passed
@Pessimistress Pessimistress deleted the claude/fix-mapbox-null-viewport-nsDGF branch March 10, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants