Repository navigation
Description
Summary
In OpenCode v2.2.6, the Code Mode execute tool returns null for every invocation — plain return values, console.log output, the global search() function, and even code that throws — while the MCP servers it is supposed to expose are healthy and connected. The result/error channel of the Code Mode runtime appears dead in this session.
Environment
- opencode version:
opencode v2.2.6(desktop app/Applications/OpenCode.app2.2.6; CLI at~/Library/Application Support/ai.opencode.desktop/cli/2.2.6-arm64/opencode-cli) - OS: Darwin 27.2.0, macOS arm64
- Terminal: OpenCode desktop app (Electron); spawned shells see
TERM=xterm-256color - Shell:
/bin/zsh - Install/channel: release 2.2.6 ("latest" channel, desktop install); server process runs as
opencode-cli serve --service - Active plugins: none found (no
pluginkey in~/.config/opencode/opencode.jsonc— only MCP server entries; no.opencode/plugin dir in the working directory) - Working directory: a non-git directory (
~/Documents/Default Project); server log showsworktree discovery failed ... Worktree.DirectoryUnavailableErrorfor it
Reproduction
- Start a session in any directory (reproduced in a non-git project dir).
- Call the Code Mode
executetool with:async function main() { return "hello"; }
- Observe the tool result:
null. - Repeat with variations — all return
null:async function main() { console.log("x"); return { a: 1 }; }async function main() { throw new Error("test error"); }(no error is surfaced)async function main() { return await search({ query: "jira" }); }(global search also returnsnull)async function main() { return await tools["<mcp-ns>"].someTool({...}); }
- Verify MCP health independently — all fine:
psshows the npx-spawned MCP server processes running (jira / confluence / bitbucket / kubernetes MCP servers).- Server log (
~/.local/share/opencode/log/opencode.log) showsmcp connected server=<jira-dc> tools=34,<bitbucket-dc> tools=21,<confluence-dc> tools=9. - Manual stdio JSON-RPC (
initialize+tools/list) against the locally spawned JIRA MCP package answers with a valid protocol handshake and tool list. - A remote MCP endpoint (internal Jenkins MCP over HTTP) answers
initializecorrectly.
- Note: during the session, harness system messages repeatedly announced "The Code Mode tool catalog has changed. This catalog supersedes the previous Code Mode tool catalog." — the
nullbehavior was identical before and after those catalog swaps.
Expected Behavior
execute runs the JavaScript in the confined Code Mode runtime and returns the final expression's value (or surfaces a thrown error), with tools.* bound to the connected MCP tool catalog and search() listing it.
Actual Behavior
Every execute call returns null. No result, no stdout, no error — thrown exceptions are swallowed into null as well, and search(...) inside execute also returns null. Reproducible consistently (10+ calls in one session), not intermittent.
Additional Context
- Server log has no ERROR entries for tools/MCP during the session — only unrelated
Failed to fetch models.devtimeouts and the worktree-discovery warnings for the non-git cwd. - A file under
~/.local/share/opencode/tool-output/contains a successful MCP (JIRA) response payload, i.e. MCP tool calls can succeed server-side while theexecuteresult channel still returnsnullto the model — pointing at the Code Mode result propagation, not at MCP connectivity. - Mid-session Code Mode catalog swaps ("catalog supersedes the previous catalog") are a plausible trigger; the harness, not the local config, changed.
- Workaround used in the affected session: drive the MCP servers manually over stdio (npx + JSON-RPC messages) or call their backing REST APIs directly with the configured credentials; regular shell/ssh/file tools are unaffected.
- Credentials, internal hostnames and tokens from the local MCP config were intentionally redacted from this report.
Activity
opencodejr commentedon Nov 9, 2026
Thanks for the detailed report! I think this is a duplicate of #57484.
In each of your examples the code declares
async function main() { ... }but never calls it.executetreatscodeas a program body: the tool description says "Prefer an explicitreturn; if omitted, the final top-level expression becomes the result." A function declaration on its own produces no value, so the result isundefined, which is turned intonull. Becausemainis never invoked, itsreturn,console.log,throw,search(...)andtools.*calls never run, which is why the thrown error doesn't show up either. Your MCP servers and the catalog changes aren't the cause.These forms should work:
Possible duplicates and related issues, ordered by likelihood:
async () => { ... }. A maintainer closed it as expected behaviour.nullfromexecutewith MCP tools; the explanation given there was a missingreturn.The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different, for example if code written as a body with an explicit
return, likereturn "hello", still returnsnullfor you.k1th commentedon Nov 9, 2026
Thanks — retested and you're right, this was a usage error on my side, not a runtime bug.
My repro snippets declared
async function main() { ... }but never invoked it. Sinceexecutetreatscodeas a program body (final top-level expression = result), the program's result was the un-invoked function declaration →undefined→null, so nothing insidemainever ran. That matches #57484 exactly.Verified on v2.2.6 in this session with correctly formed code:
return "hello";as the program body → returns"hello"return await search({ query: "searchIssues", namespace: "atlassian-jira-dc" })→ returns the tool catalogreturn await tools["atlassian-jira-dc"].jira_searchIssues({ jql: "key = EIS-289", maxResults: 1 })→ returns{ success: true, data: { total: 1, issues: [ ... ] } }MCP servers were healthy throughout (processes running,
mcp connected ... tools=34/21/9in the server log, manual stdio JSON-RPC handshake fine). One note: the MCP tool results come back wrapped as{ success, data }, which is easy to misread when indexing directly (e.g.r.issues[0]throws) — but that's just the response shape, not a bug.Happy to close as duplicate of #57484. The only mildly confusing part is that
undefined→nullis silent; the diagnostic hint proposed in #57484 ("program returned a function, invoke it") would have made this obvious immediately.opencodejr commentedon Nov 9, 2026
Thanks for retesting and confirming! Good to hear
return ...bodies,search(...)and the Jira MCP calls all work on v2.2.6.We'll keep this as a duplicate of #57484, and the bot will close it as planned. Your point about the silent
nullis the same one raised in #57484; #50577 also asks for clearer Code Mode error messages. I can't promise any change there, though.