fix(tui): guard against null/undefined MCP status in reactive computations#22206
fix(tui): guard against null/undefined MCP status in reactive computations#22206KeWang0622 wants to merge 1 commit into
Conversation
…tions
When the MCP status API returns null data, `reconcile(x.data!)` sets
`sync.data.mcp` to undefined, crashing every component that calls
Object.entries/keys/values on it.
Root fix: replace `x.data!` with `x.data ?? {}` in sync bootstrap.
Defense-in-depth: add `?? {}` / `?.` at all six consumption sites so a
stale store value can never reach Object.entries.
Closes anomalyco#22102
Closes anomalyco#21931
Closes anomalyco#21645
Closes anomalyco#21449
Closes anomalyco#21290
Closes anomalyco#20806
|
The following comment was made by an LLM, it may be inaccurate: I found potentially related PRs: PR #20444: fix(tui): add null guards for lsp and mcp state data
PR #21246: fix(tui): guard against undefined agents and mcp state during bootstrap
Both PRs are addressing similar null/undefined guard issues in MCP state handling during TUI initialization, though PR #22206 appears to be a more comprehensive fix across multiple consumption sites. |
|
Thanks for flagging the related PRs! How this PR differs from #20444 and #21246:
This PR and #21246 are complementary (MCP root cause + agent guards). #20444 is fully subsumed by this one. |
|
Friendly bump — happy to rebase or split if it helps review. TL;DR: this fixes the root cause in |
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes #22102
Closes #21931
Closes #21645
Closes #21449
Closes #21290
Closes #20806
Type of change
What does this PR do?
During TUI bootstrap,
sync.tsxfetches MCP status from the server and updates the store via:When
x.dataisnullorundefined(e.g., the server hasn't finished initializing, a network hiccup, or an SDK edge case),reconcile(undefined)setsstore.mcptoundefined. Every component that then callsObject.entries(sync.data.mcp),Object.keys(...), orObject.values(...)throws:This crash has been reported at least 6 times (#22102, #21931, #21645, #21449, #21290, #20806), primarily on Windows but reproducible on any platform with the right timing.
Root fix (sync.tsx): replace
x.data!withx.data ?? {}so the store is never set to undefined.Defense-in-depth (5 consumption sites): add
?? {}or?.at every call site that touchessync.data.mcp, so even if the store value is transiently undefined during a reactive recomputation, no component crashes. This matches the pattern already used indialog-mcp.tsx(line 35:mcpData ?? {}).Files changed
context/sync.tsxx.data!→x.data ?? {}(root cause)component/dialog-status.tsxsync.data.mcp→sync.data.mcp ?? {}(3 sites)routes/session/footer.tsxsync.data.mcp→sync.data.mcp ?? {}(2 sites)plugin/api.tsxsync.data.mcp→sync.data.mcp ?? {}(1 site)context/local.tsxsync.data.mcp[name]→sync.data.mcp?.[name](2 sites)How did you verify your code works?
bun test— all 1893 tests pass (0 fail)bun typecheck— all 13 packages pass (the husky pre-push hook ran this automatically)sync.data.mcpaccess in the TUI codebase to confirm all are now guardedScreenshots / recordings
N/A — not a visual change; this prevents a crash.
Checklist