Skip to content

analyse: surface the 3D-stage → 2D fallback instead of failing silently - #7

Open
DheerajNalapat wants to merge 1 commit into
mainfrom
fix/analyse-3d-stage-silent-2d-fallback
Open

DheerajNalapat wants to merge 1 commit into
mainfrom
fix/analyse-3d-stage-silent-2d-fallback

Conversation

@DheerajNalapat

Copy link
Copy Markdown
Collaborator

What

The /analyse room view has three modes — stage3d, room2d, fixtures. When you pick 3D stage it can silently draw the 2D room instead, and stay stuck there: the toggle keeps saying "3D stage" while the flat 2D elevation renders, with nothing on the console or the screen to explain why. Only a page reload recovers it.

Root cause

ensureStage() builds the WebGL stage lazily. On any failure it did two harmful things:

catch(e){ STAGE3D=null; }        // swallowed the exception — no console, no UI
if(!STAGE3D) STAGE3D_OK=false;   // latched false for the whole tab — never retries

So a single failure to create the stage latched the tab into the 2D fallback permanently. The most common trigger on a machine where WebGL otherwise works: Chrome caps live WebGL contexts (~16), and several open Limelight tabs (/stage, club3d.html, multiple /analyse) exhaust them, so new THREE.WebGLRenderer() throws "Too many active WebGL contexts" — swallowed, latched, stuck.

This is exactly the "Silent failures cost more than ugly ones — surface the error" rule in AGENTS.md. Not a regression: the 3D path is correct and renders fine in a clean tab (verified — Intel Mesa WebGL, createStage3D returns a real stage). The bug is the silent, permanent degrade.

Fix (synth/analyse.html only)

  1. Don't swallowconsole.warn the real exception, and record the reason.
  2. Surface it — a note beside the view button: "· 3D stage unavailable (<reason>) — showing 2D room", cleared when 3D is live.
  3. Stop latching permanently — the one-attempt guard is now per selection (STAGE3D_TRIED), and re-selecting the 3D stage clears it, so a failure that has since cleared (a freed WebGL context) recovers without a reload.

Verification

Reproduced and verified on the running portal by forcing createStage3D to throw:

before after
console on failure silent (0 warnings) console.warn with the real error
on-screen notice none "3D stage unavailable (…) — showing 2D room"
re-select 3D after WebGL frees still 2D (latched) recovers to live 3D
healthy path 3D 3D, note stays empty

No other files touched.

🤖 Generated with Claude Code

When createStage3D failed once -- most often Chrome's live-WebGL-context
limit, hit with several Limelight tabs open -- ensureStage() swallowed the
exception and latched STAGE3D_OK=false for the tab. Every later frame then
drew the 2D room while the toggle still read "3D stage", with nothing on the
console or the screen to say why, and only a reload recovered it. That is the
silent failure the notes warn against.

Now the fall-back is loud: a console.warn carrying the real error, and a note
beside the view button -- "3D stage unavailable (<reason>) -- showing 2D room".
And the build guard is per selection rather than permanent, so re-selecting
the 3D stage retries a build that has since become possible (a freed WebGL
context, say) without reloading the page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants