Skip to content

Stop a render error from blanking the whole app - #56

Open
Carlsaurus wants to merge 1 commit into
mainfrom
fix/frontend-error-boundary
Open

Stop a render error from blanking the whole app#56
Carlsaurus wants to merge 1 commit into
mainfrom
fix/frontend-error-boundary

Conversation

@Carlsaurus

Copy link
Copy Markdown
Contributor

The problem

The frontend has no error boundary anywhere:

grep -rn "ErrorBoundary|componentDidCatch|getDerivedStateFromError" frontend/src  →  (nothing)

In React that means any exception thrown during render unmounts the entire tree. Every render bug then looks identical — a white page, no message, no stack, nothing to report. That's how "press Optimize on the flight page and it goes blank" reached us with nothing actionable.

The fix

Adds components/ErrorBoundary.tsx and wraps each of the nine tab panels. The tab buttons live in <header>, above the panels, so a crashing tab now shows a copyable error with its component stack and a Try again button — while the tab bar stays alive and every other tab keeps working.

Verified end to end

Not just by inspection. I injected a throw at the top of FlightSimulation, reloaded, and confirmed the boundary rendered "Flight Simulation hit an error" with the stack, while the header, all nine tabs, and every other panel stayed mounted and usable. Then reverted the throw and confirmed a clean load.

What this does not do

It does not by itself remove the underlying throw on the flight-optimize path — I could not reproduce that one. The handler is correctly guarded (checks result.error, checks result.data, wrapped in try/catch — though try/catch does not cover render), and every field the flight UI renders is a required float or List[float] in the backend models, with all Optional sub-objects already guarded (results?.truncation?., results.propellant &&, and the !results?.trajectory early return).

With the boundary in place, the next occurrence prints the real error instead of a blank page — which is what makes it fixable.

Notes

The Try again button is declared VIEW_ONLY in the checkout gating audit: it clears local error state and touches no design state.

Frontend gating audit 4 passed; npm run build clean.

🤖 Generated with Claude Code

The frontend had NO error boundary anywhere -- grep for ErrorBoundary /
componentDidCatch / getDerivedStateFromError returned nothing. In React that
means any exception thrown during render unmounts the ENTIRE tree, so every
render bug presents identically: a white page, no message, no stack, no way to
report what happened. That is how "press Optimize on the flight page and it
goes blank" arrived with nothing to act on.

Adds components/ErrorBoundary.tsx and wraps each of the nine tab panels in one.
The tab buttons live in <header>, above the panels, so a crashing tab now shows
a copyable error with its component stack and a Try again button while the tab
bar stays alive and every other tab keeps working.

Verified end to end, not just by inspection: injected a throw at the top of
FlightSimulation, reloaded, and confirmed the boundary rendered "Flight
Simulation hit an error" with the stack while the rest of the app -- header,
all nine tabs, the other panels -- stayed mounted and usable. Throw reverted.

Note this does not by itself remove the underlying throw on the flight optimize
path. I could not reproduce that one: the handler is correctly guarded (checks
result.error, checks result.data, wrapped in try/catch -- though try/catch does
not cover render), and every field the flight UI renders is a REQUIRED float or
List[float] in the backend models, with all Optional sub-objects already guarded
(results?.truncation?., results.propellant &&, and the !results?.trajectory
early return). With the boundary in place the next occurrence prints the real
error instead of a blank page, which is what makes it fixable.

The Try again button is declared VIEW_ONLY in the checkout gating audit: it
clears local error state and touches no design state.

Frontend gating audit 4 passed; npm run build clean.

Co-Authored-By: Claude Opus 5 <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.

1 participant