Skip to content

[Sentry: APP-HV3] Web crash creating Skia WebGL surface on expense report — null shader precision format #98101

Description

@mountiny

Sentry

https://expensify.sentry.io/issues/APP-HV3

Impact (snapshot at filing)

  • Users (last 7d): 21
  • Users (total since first seen): 44
  • Events: 338
  • First seen: 2026-07-16
  • Last seen: now (ongoing)
  • Platform: web (Chrome on Windows and macOS)
  • App version(s): 9.4.50-3 and earlier
  • Affected route(s) (parameterized): /e/:reportID (view name ExpenseReport)
  • Mechanism: auto.browser.browserapierrors.setTimeout

Stack trace (top frames)

@shopify/react-native-skia/lib/module/views/SkiaPictureView.web.js:248 (b)
    renderer.current = new WebGLRenderer(canvas, pd)
@shopify/react-native-skia/lib/module/views/SkiaPictureView.web.js:26 (new s)
    this.onResize();
@shopify/react-native-skia/lib/module/views/SkiaPictureView.web.js:45 (s.onResize)
    const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);
canvaskit-wasm/bin/full/canvaskit.js (MakeWebGLCanvasSurface)
canvaskit-wasm/bin/full/canvaskit.js (MakeWebGLContext)
canvaskit-wasm/bin/full/canvaskit.js (_MakeGrContext)
canvaskit-wasm/bin/full/canvaskit.js:256
    a = X.getShaderPrecisionFormat(a, b); Q[d >> 2] = a.rangeMin;

Suspected cause

WebGLRenderingContext.getShaderPrecisionFormat() returns null when the WebGL context is lost or unavailable. CanvasKit dereferences the result without a null check, so the read of .rangeMin throws and the crash surfaces as an unhandled error.

Every sampled event runs low on memory at the time of the crash (95% to 97% heap usage), which fits a browser dropping the WebGL context under memory pressure and Skia then trying to build a surface on a dead context.

Suggested fixes, in order of preference:

  1. Guard the Skia canvas on web. Check that a WebGL context is actually available before mounting SkiaPictureView, and render a non-Skia fallback when it is not.
  2. Handle the webglcontextlost event on the canvas and skip surface creation while the context is gone.
  3. If neither is practical in app code, raise the missing null check upstream in canvaskit-wasm.

Reproduction

Unknown from the events alone. To approximate it: open an expense report on web, then force the browser to drop the WebGL context (for example with the WEBGL_lose_context extension, or by opening enough memory-heavy tabs to trigger context eviction).

Related

Upwork Automation - Do Not Edit

Metadata

Metadata

Labels

#qualityRelates to work in the #quality roomBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorOverdue

Type

No type

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions