anomalyco / anomalyco/opencode

tui: Host.resolve treats Bun ResolveMessage as fatal for missing plugin subpaths

Open
#48,122 1 comment 0 reactions 1 assignee View on GitHub

@kitlangton is already working on this.

Since Sep 9, 2026.

2.0
Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

packages/plugin/src/host.ts is intended to probe several conventional plugin entrypoints and continue when a subpath is missing. Under Bun 1.3.14, Bun.resolveSync throws a ResolveMessage for a missing module or package export. That object has a whitelisted code on its prototype, but it does not extend Error:

constructor: ResolveMessage
error instanceof Error: false
"code" in error: true
error.code: ERR_MODULE_NOT_FOUND
own properties: []

At source revision 9128e847bdbf9e5a58b7bdc33896e484e745aedd, packages/plugin/src/host.ts:25-38 first requires error instanceof Error. The first missing conventional subpath is therefore rethrown instead of being skipped.

Two real targets reproduce different points in the probe sequence:

local directory with index.ts but no server.ts:
Cannot find module '<plugin>/server'

opencode-usage-stat@2.4.5, which exports ./server and ./tui but not ./rpc:
Cannot find module 'opencode-usage-stat/rpc'

The TUI plugin panel showed these targets as failed, while the server log shows both server entrypoints loading normally. Whether the packaged server's embedded Bun represents ResolveMessage in exactly the same way is uncertain; the deterministic reproduction and fix below use the source/dev TUI on system Bun 1.3.14, connected to the beta service.

A local fix replaced the instanceof Error gate with a string code check against the existing whitelist. After that change, both targets resolve as expected:

local: { server: "file://.../index.ts", tui: undefined, rpc: undefined }
usage-stat: { server: "file://.../dist/server.js", tui: "file://.../dist/tui.jsx", rpc: undefined }

Suggested fix in packages/plugin/src/host.ts:25-38: read (error as { code?: unknown }).code, require it to be a string, and apply the current missing-path whitelist without requiring error instanceof Error.

Plugins
  • Local opencode-enhanced-subagent directory (index.ts, no server.ts)
  • opencode-usage-stat@2.4.5 (exports ., ./server, and ./tui, but no ./rpc)
OpenCode version

TUI source at 9128e847bdbf9e5a58b7bdc33896e484e745aedd, connected to opencode2 v0.0.0-beta-19271; Bun 1.3.14.

Steps to reproduce
  1. With Bun 1.3.14, call Bun.resolveSync("<local-plugin>/server", "<local-plugin>") for a plugin directory that has index.ts but no server.ts.
  2. Observe a ResolveMessage with code === "ERR_MODULE_NOT_FOUND" and instanceof Error === false.
  3. Call the current Host.resolve({ directory: "<local-plugin>" }) implementation. It throws on /server instead of falling back to /index.
  4. Alternatively, call Host.resolve for an installed package that exports server/TUI entrypoints but no ./rpc; it resolves the first two and then throws on the missing RPC export.
  5. Replace the instanceof Error gate with a typed string-code check and repeat. Both calls return complete Entrypoints objects without throwing.

Expected: missing optional/conventional subpaths whose error code is in the existing whitelist are skipped, regardless of whether Bun's thrown object extends Error.

Actual: every Bun ResolveMessage fails the instanceof Error check and becomes fatal.

Screenshot and/or share link

No screenshot. The exact probe output is included above.

Operating System

WSL2 Ubuntu, Linux 6.18.33.2-microsoft-standard-WSL2 x86_64.

Terminal

TERM=xterm-256color, shell /bin/bash.

Local verification notes
  • Reproduced both failing targets with the exact pre-fix predicate from packages/plugin/src/host.ts.
  • Applied and tested the narrow predicate change locally in commit 977afc6c74948533addda46f6653e9511146451f.
  • Re-ran both real-target probes successfully after the change.
  • Ran bun test test/host.test.ts from packages/plugin: 9 passed, 0 failed.
  • The claim that c72b535dee predates this path is not correct: that revision's packages/tui/src/plugin/context.tsx:607 already calls Host.resolve(target).tui. The guard itself was introduced by ed3259a9b7 before c72b535dee.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.