Skip to content

Force WebGL context loss on Canvas cleanup to prevent GPU leaks - #946

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-webgl-context-leak
Draft

Force WebGL context loss on Canvas cleanup to prevent GPU leaks#946
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/fix-webgl-context-leak

Conversation

@posthog

@posthog posthog Bot commented Jul 2, 2026

Copy link
Copy Markdown

Summary

The main render Canvas.tsx calls renderer.dispose() on teardown but never renderer.forceContextLoss(), so each unmount leaked its WebGL context. Once enough live contexts accumulate, the browser silently force-loses the oldest one; three.js then calls gl.createShader() on the dead context, gets back null, and throws:

TypeError: Argument 1 ('shader') to WebGL2RenderingContext.shaderSource must be an instance of WebGLShader

This mirrors the fix already applied to the sibling OrientationCubeCanvas.tsx in #673.

The change also splits the single mount effect in two: the renderer is now created once and reused, while only the camera is rebuilt when cameraType changes. Previously every camera-type switch tore down and recreated the whole renderer (and its GPU context), churning through contexts unnecessarily. The active camera lives in a ref so the animation/resize loops always read the current one.

Why

A user hit a WebGL context-loss crash in the 3D viewer. The root cause is the leaked GPU contexts on unmount, which compound for anyone who opens or switches between many viewers in a session.

Test plan

  • npx tsc --noEmit passes
  • npm run build succeeds
  • Camera-type switching still restores camera position (state saved on the camera effect's cleanup, restored on rebuild)

Created with PostHog Code from an inbox report.

The main render Canvas called renderer.dispose() on teardown but never
renderer.forceContextLoss(), so each unmount leaked its WebGL context.
Once enough live contexts pile up, the browser force-loses the oldest,
three.js then calls createShader() on the dead context, gets null, and
throws in shaderSource().

Mirrors the fix already applied to OrientationCubeCanvas in #673. Also
splits the single effect so the renderer is created once and only the
camera is rebuilt on camera-type changes, instead of tearing down and
recreating the whole renderer (and its context) on every switch.

Generated-By: PostHog Code
Task-Id: 5ccbf1fc-0307-4461-9b52-9ff34cf8bfae
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
3d-viewer Ready Ready Preview, Comment Jul 2, 2026 10:20pm

Request Review

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.

0 participants