Skip to content

fix(game): survive the pdf-only analysis result window - #202

Merged
marota merged 1 commit into
ainetus:mainfrom
marota:claude/co-study4grid-overflow-error-mtwp20
Aug 3, 2026
Merged

fix(game): survive the pdf-only analysis result window#202
marota merged 1 commit into
ainetus:mainfrom
marota:claude/co-study4grid-overflow-error-mtwp20

Conversation

@marota

@marota marota commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Game Mode crashed with "TypeError: Cannot convert undefined or null to object" whenever the operator ran Analyze & Suggest, right as the overflow graph became available.

Step 2 streams a pdf event (emitted as soon as the overflow-graph file is written) seconds before the result event that carries the actions. The pdf branch merged into the previous result:

setResult(p => ({ ...(p || {}), pdf_url, pdf_path, ... }))

On a first analysis p is null, so the resulting object had NO actions key — despite AnalysisResult declaring it required (the as AnalysisResult cast hid it from the type checker). The Game Mode snapshot effect then ran Object.keys(result.actions) on that intermediate state and threw, taking down the app through the error boundary. The classic workspace was unaffected because that effect is behind gameBridge.isGameMode().

Seed actions on the pdf merge so a partial result is always structurally valid, and harden the two Game Mode consumers that read the map unguarded (the snapshot effect and buildChosenActionRecord / combinedBeatsUnderlying, which would have thrown next once an action was starred).

Both regression tests fail without the fix.

Claude-Session: https://claude.ai/code/session_01FSWwhkaPiAsxasECiBws8k

Game Mode crashed with "TypeError: Cannot convert undefined or null to
object" whenever the operator ran Analyze & Suggest, right as the
overflow graph became available.

Step 2 streams a ``pdf`` event (emitted as soon as the overflow-graph
file is written) seconds before the ``result`` event that carries the
actions. The pdf branch merged into the previous result:

    setResult(p => ({ ...(p || {}), pdf_url, pdf_path, ... }))

On a first analysis ``p`` is null, so the resulting object had NO
``actions`` key — despite ``AnalysisResult`` declaring it required (the
``as AnalysisResult`` cast hid it from the type checker). The Game Mode
snapshot effect then ran ``Object.keys(result.actions)`` on that
intermediate state and threw, taking down the app through the error
boundary. The classic workspace was unaffected because that effect is
behind ``gameBridge.isGameMode()``.

Seed ``actions`` on the pdf merge so a partial result is always
structurally valid, and harden the two Game Mode consumers that read
the map unguarded (the snapshot effect and ``buildChosenActionRecord`` /
``combinedBeatsUnderlying``, which would have thrown next once an action
was starred).

Both regression tests fail without the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSWwhkaPiAsxasECiBws8k
Signed-off-by: Antoine Marot <amarot91@gmail.com>
@marota
marota merged commit 43eff2f into ainetus:main Aug 3, 2026
12 checks passed
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