Skip to content

fix(deckgl): prevent crash on Intel integrated GPUs when satellite imagery layer fails#2696

Merged
koala73 merged 3 commits intokoala73:mainfrom
fuleinist:fix/deckgl-satellite-crash
Apr 6, 2026
Merged

fix(deckgl): prevent crash on Intel integrated GPUs when satellite imagery layer fails#2696
koala73 merged 3 commits intokoala73:mainfrom
fuleinist:fix/deckgl-satellite-crash

Conversation

@fuleinist
Copy link
Copy Markdown
Contributor

Summary

Prevents the desktop app from crashing when the deck.gl satellite imagery layer's stroke fragment shader fails to compile on Intel integrated GPUs (Intel i-series with integrated graphics on Windows 11).

Root cause

The fragment shader satellite-imagery-layer-stroke-fragment fails to compile on Intel integrated GPUs. The existing onError handler only caught apt-groups-layer errors, so this unhandled shader compilation error caused the app to crash.

Changes

  1. deck.gl 9.2.6 → 9.2.11: Latest patch version with improved Intel GPU shader workarounds
  2. Graceful degradation for satellite imagery layer: Extended onError handler to catch satellite-imagery-layer errors and set satelliteImageryLayerFailed = true. When this flag is set, the satellite imagery layer is skipped in buildLayers() — matching the existing pattern used for apt-groups-layer. Also calls showLayerWarning() so users understand why satellite imagery disappeared.
  3. Prevents app crash: Users with Intel integrated GPUs can now use the app with satellite imagery disabled automatically

Testing

  • TypeScript compilation passes
  • No breaking changes to existing layer rendering logic
  • Follows same graceful-degradation pattern as apt-groups-layer

Closes #2518

…agery layer fails

- Update deck.gl 9.2.6 → 9.2.11 (latest patch with improved Intel GPU workarounds)
- Extend onError handler to catch satellite-imagery-layer shader compilation failures
- Skip satellite imagery layer gracefully when WebGL shader compilation fails (prevents app crash)
- Follows same graceful-degradation pattern used for apt-groups-layer errors
- Add showLayerWarning when satellite layer fails so users understand why imagery disappeared

Fixes koala73#2518
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 4, 2026

Someone is attempting to deploy a commit to the World Monitor Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 4, 2026

Greptile Summary

This PR attempts to prevent desktop app crashes on Intel integrated GPUs by (1) upgrading deck.gl from 9.2.6 → 9.2.11 for improved Intel GPU shader workarounds, and (2) extending the existing onError handler in DeckGLMap.ts to catch satellite-imagery-layer shader compilation failures and set a satelliteImageryLayerFailed flag that gates the layer out of subsequent buildLayers() calls — mirroring the existing apt-groups-layer graceful-degradation pattern.

The approach is sound in principle, but there is a critical defect in the implementation:

  • WARN_THRESHOLD is out of scope (P0): The identifier WARN_THRESHOLD referenced at line 839 inside the onError callback is only defined as a local const inside enforceLayerLimit() (line 5443). It is not a module-level or class-level constant. This is a TypeScript compilation error and, if bypassed, a runtime ReferenceError — meaning the crash-recovery code itself would crash in the exact failure scenario it is designed to handle.
  • Misleading user warning (P1): showLayerWarning(threshold) is purpose-built for the "too many layers active" scenario and populates its dialog body with t('components.deckgl.layerWarningBody', { threshold }). Firing it for a GPU shader compilation failure tells the user their app is slow because too many layers are active, rather than informing them that satellite imagery was disabled due to a GPU driver incompatibility. The existing apt-groups-layer error path deliberately does not call showLayerWarning().
  • No immediate layer rebuild after failure (P2): After setting satelliteImageryLayerFailed = true, the failed layer is not explicitly flushed from deck.gl's render list until the next natural buildLayers() call; a debouncedRebuildLayers() call would remove it immediately.

Confidence Score: 1/5

Not safe to merge: the crash-recovery code itself contains a scoping error that will throw a ReferenceError in the exact failure scenario it targets.

The core logic (flag + gate in buildLayers) is correct and follows the established pattern, and the deck.gl version bump is straightforward. However, the WARN_THRESHOLD reference at line 839 is a variable that does not exist in that scope — this is a P0 bug that would cause a ReferenceError at the moment the Intel GPU error fires, negating the entire crash-fix. The misleading showLayerWarning() call is a P1 UX regression on top of that.

src/components/DeckGLMap.ts lines 837-840 (onError satellite-imagery-layer branch)

Important Files Changed

Filename Overview
src/components/DeckGLMap.ts Extends onError handler to catch satellite-imagery-layer failures; introduces a reference to WARN_THRESHOLD that is out-of-scope (P0 ReferenceError) and calls showLayerWarning() with semantically incorrect framing for a GPU shader failure (P1).
package.json Bumps all @deck.gl/* packages and deck.gl from 9.2.6 to 9.2.11 for improved Intel GPU shader workarounds; no other dependency changes.
package-lock.json Lock file updated to reflect deck.gl 9.2.11 transitive dependency tree; no unexpected changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[deck.gl renders frame] --> B{onError fires?}
    B -- No --> C[Frame rendered OK]
    B -- Yes --> D{error.message includes apt-groups-layer?}
    D -- Yes --> E[aptGroupsLayerFailed = true]
    D -- No --> F{error.message includes satellite-imagery-layer?}
    F -- Yes --> G[satelliteImageryLayerFailed = true]
    G --> H[showLayerWarning WARN_THRESHOLD - out of scope - ReferenceError]
    F -- No --> I[error logged, ignored]
    E --> J[Next buildLayers call]
    H --> J
    J --> K{satelliteImageryLayerFailed?}
    K -- true --> L[Skip createImageryFootprintLayer]
    K -- false --> M[Include satellite-imagery-layer]
    L --> N[Layer stack returned]
    M --> N
Loading

Reviews (1): Last reviewed commit: "fix(deckgl): prevent crash on Intel inte..." | Re-trigger Greptile

Comment thread src/components/DeckGLMap.ts Outdated
}
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(WARN_THRESHOLD);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P0 WARN_THRESHOLD is not in scope — likely a ReferenceError

WARN_THRESHOLD is only defined as a local const inside enforceLayerLimit() at line 5443. It is not a module-level or class-level constant and is therefore completely out of scope inside the onError callback here.

This should cause a TypeScript compilation error (Cannot find name 'WARN_THRESHOLD'). If the build somehow succeeds, this will throw a ReferenceError at runtime whenever the satellite imagery layer fails on an Intel GPU — the exact crash scenario this PR is meant to fix.

The fix should use a numeric literal directly (matching the existing WARN_THRESHOLD = 13 value), or extract WARN_THRESHOLD to a module-level constant shared between enforceLayerLimit() and this handler:

Suggested change
showLayerWarning(WARN_THRESHOLD);
showLayerWarning(13);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. has been replaced with a GPU-specific followed by . The local const (value 13) is no longer referenced in the callback, eliminating the ReferenceError. The layer stack is now rebuilt immediately after the satellite imagery layer fails.

Comment on lines +837 to +840
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(WARN_THRESHOLD);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 showLayerWarning() shows the wrong message for a GPU shader failure

showLayerWarning(threshold) was built to tell users "You have more than {threshold} layers active, which may degrade performance" (see t('components.deckgl.layerWarningBody', { threshold }) in src/utils/layer-warning.ts). Calling it here for a GPU shader compilation failure will display a deeply misleading message — the user will believe they have too many layers active, when the real cause is an Intel GPU driver incompatibility.

The apt-groups-layer handler deliberately does not call showLayerWarning() (it only sets the flag), so this is also inconsistent with the existing pattern.

A dedicated warning — even a simple console.warn plus a toast/notification — that explains satellite imagery was disabled due to a GPU compatibility issue would be far more helpful to the user.

Suggested change
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(WARN_THRESHOLD);
}
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
// TODO: show a GPU-specific warning to the user here
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Removed the misleading showLayerWarning() call. Replaced with a descriptive console.warn targeting the Intel GPU driver incompatibility scenario. The onError callback now logs a clear GPU-specific message instead of incorrectly telling users they have too many layers active.

Comment on lines +837 to +840
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(WARN_THRESHOLD);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Layer not immediately removed after failure

After setting satelliteImageryLayerFailed = true, no explicit rebuild of the layer stack is triggered. The failed layer remains in deck.gl's render list until the next natural buildLayers() call (e.g., on moveend or zoomend). For the apt-groups-layer this is acceptable since it's a static dataset, but satellite imagery is actively fetched on every viewport change — users may see the broken layer linger.

Consider adding a debouncedRebuildLayers() call to flush the failed layer immediately:

Suggested change
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(WARN_THRESHOLD);
}
if (error.message.includes('satellite-imagery-layer')) {
this.satelliteImageryLayerFailed = true;
showLayerWarning(13);
this.debouncedRebuildLayers();
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Added debouncedRebuildLayers() call immediately after setting satelliteImageryLayerFailed = true. The failed satellite imagery layer is now removed from deck.gl's render list on the very next frame, rather than waiting for the next moveend/zoomend event. Combined with the GPU-specific console.warn (addressing P1), this gives users immediate feedback and correct layer state.

fuleinist and others added 2 commits April 5, 2026 10:08
…la73#2696

P0: Replace out-of-scope WARN_THRESHOLD with debouncedRebuildLayers()
     WARN_THRESHOLD was a local const inside enforceLayerLimit(), not
     accessible in the onError callback — would cause ReferenceError at
     runtime on Intel GPU failures.

P1: Replace misleading showLayerWarning() with GPU-specific console.warn
     showLayerWarning() tells users they have too many layers active,
     which is deeply misleading for a GPU shader compilation failure.
     Now logs a descriptive GPU incompatibility message instead.

P2: Trigger immediate layer stack rebuild after satellite layer failure
     Added debouncedRebuildLayers() call so the failed layer is removed
     from deck.gl's render list immediately rather than waiting for the
     next moveend/zoomend event.

Fixes greptile-apps review comments:
  - 3036106846 (P0): WARN_THRESHOLD not in scope
  - 3036106896 (P1): showLayerWarning() wrong message
  - 3036106953 (P2): layer not immediately removed
The debounced rebuild leaves a 150ms window where the broken layer
is still in deck.gl's picking pipeline. A hover/click during that
window can trigger the same crash this PR prevents. Use immediate
setProps instead.
@koala73 koala73 merged commit 2ad249d into koala73:main Apr 6, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trust:safe Brin: contributor trust score safe

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: orbital surveillance crashing

2 participants