fix(config): clone global cache to prevent cross-workspace mutation leak - #41950
Open
weiconghe wants to merge 1 commit into
Open
fix(config): clone global cache to prevent cross-workspace mutation leak#41950weiconghe wants to merge 1 commit into
weiconghe wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #41916
Type of change
What does this PR do?
Config.loadInstanceStatemerges the process-global config cache into the per-workspace result via remedamergeDeep. When the workspace has no project-level value for a nested key (e.g.mcp),mergeDeepcopies the same object reference from the global cache into the result — verified against remeda 2.26.0:Plugin
confighooks receive the workspace's live config-state object (packages/opencode/src/plugin/index.ts:245) and commonly mutate it in place (config.mcp[name] ??= {...}). When the workspace config shares a nested reference with the global cache, those writes leak back intocachedGlobal— which hasDuration.infinityTTL. Every other workspace attached to the sameopencode serveprocess then sees the leaked MCP servers (or any other nested config) in its/mcpstatus.Fix:
structuredClonethe cached global config before merging it into the per-workspace result. TheloadGlobal(authEnv)path already returns freshly parsed objects (no caching), so only thegetGlobal()path needs cloning.How did you verify your code works?
Added a regression test in
test/config/config.test.tsthat:mcp(no project-level override)cfg.mcp.injected = {...})Config.use.getGlobal()does not see the mutationThe test fails without the fix (
globalCfg.mcp.injectedis the injected object) and passes with it. Full config test suite: 93 pass, 4 pre-existing Windows-specific failures (unrelated —ENOENTon.jsoncauto-creation, Git Bash/Cygwin path timeout, permission key-order on Windows).Note: the test clears
OPENCODE_CONFIG_DIRbecause a developer's local config may containmcp: {}, which incidentally breaks the shared reference chain viamergeDeepand masks the bug.Screenshots / recordings
N/A
Checklist