-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Description
When using OpenCode Web UI (opencode web), switching between workspaces causes Instance.directory to resolve to a non-existent path containing a base64-encoded directory name. This causes all local MCP server processes to fail with ENOENT on posix_spawn, leaving sessions without any local MCP tools.
Environment
- OpenCode version: 1.2.24 (upgraded to 1.3.0, untested yet)
- Runtime: Bun
- OS: Debian 12 (bookworm)
- Setup:
opencode web --port 3002running as systemd service per user, 10 concurrent user instances on same server - MCP servers: 2 local (
uvfor Python,nodefor JS), 1 remote (HTTP)
Reproduction
- Start
opencode web --port 3002as a systemd service - Open the Web UI and create a session in workspace
/home/eva/workspace - MCP servers start correctly — all 97 tools from
unified-adsload fine - Navigate to a different workspace or create additional sessions
- At some point, a new Instance is created where
Instance.directoryresolves to a base64-encoded path appended to the original workspace path
Observed Behavior
From the logs (~/.local/share/opencode/log/2026-03-12T065837.log):
Working (06:59) — real directory:
service=mcp key=unified-ads toolCount=97 create() successfully created client
directory=/home/eva/workspace
Working (07:06) — another real directory:
service=mcp key=unified-ads toolCount=97 create() successfully created client
directory=/home/eva
Broken (07:07) — base64-encoded path:
ERROR service=mcp key=unified-ads cwd=/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ error=ENOENT: no such file or directory, posix_spawn '/usr/local/bin/uv' local mcp startup failed
ERROR service=mcp key=imagemaker cwd=/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ error=ENOENT: no such file or directory, posix_spawn 'node' local mcp startup failed
An earlier log also shows:
cwd=Lw error=ENOENT ...
The string L2hvbWUvZXZhL3dvcmtzcGFjZQ is base64 of /home/eva/workspace.
The string Lw is base64 of /.
OpenCode's Web UI uses base64-encoded paths in URL routing (/<base64-dir>/session/<id>). It appears this base64 string is being used as a literal filesystem path for Instance.directory instead of being decoded first.
Impact
- ALL local MCP servers fail (
uv,node) — bothunified-ads(Python/FastMCP) andimagemaker(Node.js) hit the same error - Only remote/HTTP MCP servers survive (they don't need
posix_spawn) - Users see sessions where MCP tools are completely missing with no clear error in the UI
- The
ENOENTerror message is misleading — it blames the executable (/usr/local/bin/uv) rather than the CWD (known Bun bug: Bun.spawn throws incorrect ENOENT error when cwd does not exist oven-sh/bun#24012)
Evidence This Is Not an MCP Configuration Issue
- Two completely independent MCP servers (Python via
uv, Node.js vianode) fail identically - Both executables exist and work fine —
which uv→/usr/local/bin/uv,which node→/usr/bin/node - The MCP config is correct and works when
Instance.directoryis a real path - OpenCode itself logs
No such file or directory: '/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ'
Expected Behavior
Instance.directory should always resolve to a valid filesystem path. If the Web UI uses base64-encoded paths for URL routing, these should be decoded back to real paths before being used as CWD for MCP process spawning.
Potentially Related Issues
- Bug Report: Opencode Server Fails with ENOENT posix_spawn '/usr/bin/rg' When Directory Parameter is Provided #3158 —
posix_spawnENOENT when?directory=parameter points to non-existent path (closed/fixed) - [BUG]: Session switching doesn't change working directory context #6697 —
Instance.directorynot updating when switching sessions (closed/fixed) - opencode serve uses / as base directory when started from non-root path allowing access to arbitrary locations + permission path mismatches #14445 —
opencode servedefaults to/as base directory - Per-session MCP server and LSP duplication multiplies memory usage across concurrent sessions #13041 — Per-session MCP/LSP duplication
- Bun.spawn throws incorrect ENOENT error when cwd does not exist oven-sh/bun#24012 — Bun reports ENOENT for executable instead of CWD
MCP Config (for reference)
{
"unified-ads": {
"type": "local",
"command": ["/usr/local/bin/uv", "run", "--directory", "/opt/mcp/adsmcp", "python", "-m", "unified_ads_mcp"],
"enabled": true,
"environment": {
"HOME": "/home/eva",
"GOOGLE_ADS_CREDENTIALS": "/home/eva/google-ads.yaml",
"META_ADS_CREDENTIALS": "/home/eva/meta-ads.yaml"
}
}
}Note: There is no cwd field in the McpLocal schema (.strict() validation), so there is no workaround from the configuration side.
Suggested Fix
In the MCP spawning code, either:
- Decode the base64 path back to a real filesystem path before using it as CWD
- Validate that
Instance.directoryexists before passing it toBun.spawn() - Fall back to a safe default CWD (e.g., user's home directory or
/tmp) if the directory doesn't exist - Add a
cwdoption to theMcpLocalschema so users can specify a fixed working directory for MCP processes