[BUG] Race Condition: Folders Created with Literal Variable Names Before Expansion
[BUG] Race Condition: Folders Created with Literal Variable Names Before Expansion
Description
Claude Code creates directories with literal unexpanded variable names (e.g., ${CLAUDE_CODE_DATA_DIR}) during initialization, before environment variable expansion occurs. The MCP servers then correctly use the expanded paths, resulting in duplicate folders.
This is distinct from #9427 where variables don't expand at all - in this case, MCP servers work correctly with expanded values, but something in the initialization phase creates folders too early.
Steps to Reproduce
- Define a custom environment variable in
.claude/settings.local.json:
``json``
"env": {
"CLAUDE_CODE_DATA_DIR": "/home/user/claude-code-data"
}
- Reference it in a plugin's
plugin.jsonMCP server configuration:
``json``
"mcpServers": {
"chroma": {
"command": "uvx",
"args": [
"chroma-mcp",
"--data-dir",
"${CLAUDE_CODE_DATA_DIR}/chroma"
]
},
"slack": {
"env": {
"SLACK_MCP_USERS_CACHE": "${CLAUDE_CODE_DATA_DIR}/.slack_users_cache.json"
}
}
}
- Start Claude Code
- Check project directory with
ls -la
Expected Behavior
- Only the expanded path (
/home/user/claude-code-data/chroma) should be created - No folder named literally
${CLAUDE_CODE_DATA_DIR}should exist in the project directory
Actual Behavior
$ ls -la /home/jurgen/sites/claude-agents/
drwxrwxr-x 3 jurgen jurgen 4096 Dec 5 12:32 ${CLAUDE_CODE_DATA_DIR} # ← Literal folder created!
$ ls -la /home/jurgen/claude-code-data/
drwxrwxr-x 3 jurgen jurgen 4096 Dec 5 12:32 chroma # ← Correct expanded path
-rw-r--r-- 1 jurgen jurgen 66190 Dec 5 03:25 .slack_channels_cache.json
-rw-r--r-- 1 jurgen jurgen 134061 Dec 5 03:25 .slack_users_cache.json
Evidence:
- MCP servers successfully write data to expanded path
/home/jurgen/claude-code-data/ - Literal
${CLAUDE_CODE_DATA_DIR}/folder exists but remains empty - Both folders coexist, proving this is a timing issue not an expansion failure
Impact
- Creates confusing literal
${...}folders in project directories - Pollutes workspaces with stale empty directories
- Wastes disk space with duplicate directory trees
- Makes debugging MCP server paths confusing (which folder is being used?)
Root Cause (Analysis)
This appears to be a race condition in the initialization sequence:
- ✅ Settings are loaded
- ❌ Something creates directories (pre-flight check? MCP setup?) - uses literal strings
- ✅ Environment variables are expanded
- ✅ MCP servers start with correct expanded values
The directory creation logic runs before variable expansion, but MCP server execution runs after expansion.
Relationship to Existing Issues
- #9427 (open) - Variables not expanding in plugin
.mcp.jsonfor authentication - #3239 (closed, regressed) - Variable expansion not working in
.mcp.json - #7960 - Unwanted directory creation in CWD
This bug is distinct: MCP servers work correctly, but something creates directories too early.
Environment
- Platform: Linux 6.14.0-36-generic
- Claude Code version: [latest as of 2025-12-05]
- Plugin: Custom plugin with MCP servers (chroma, slack, gitlab)
- Variable defined in:
.claude/settings.local.json - Variable used in:
.claude-plugin/plugin.json
Suggested Fix
Ensure environment variable expansion happens before:
- Any directory creation related to MCP server paths
- MCP server argument/config pre-processing
- Pre-flight checks that might create directories
Workaround
None known - literal folders must be manually deleted periodically.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗