📋 Pre-flight Checks
📝 Bug Description
The background-agents.ts plugin fails to load entirely on OpenCode Desktop 1.2.27. Two separate errors occur in sequence, each preventing the plugin from initializing.
🔄 Steps to Reproduce
- Install background-agents.ts in ~/.config/opencode/plugins/
- Launch OpenCode Desktop 1.2.27
- Observe sidecar logs
✅ Expected Behavior
The plugin loads successfully and registers the delegate, delegation_read, and delegation_list tools.
❌ Actual Behavior
Two sequential errors in the sidecar logs:
Error 1:
service=plugin error=Cannot call a class constructor TimeoutError without |new|
Cause: OpenCode's plugin bundler transpiles ES6 class syntax to functions. When
TimeoutError extends Error is transpiled, calls to new TimeoutError(...) inside
Promise.race() lose the new keyword, crashing the constructor.
Fix: Replace the class with an interface + factory function:
interface TimeoutError extends Error { readonly name: "TimeoutError"; readonly timeoutMs: number }
function makeTimeoutError(message: string, timeoutMs: number): TimeoutError { ... }
function isTimeoutError(e: unknown): e is TimeoutError { return e instanceof Error && (e as any).name === "TimeoutError" }
Error 2 (after fixing Error 1):
service=plugin error=undefined is not an object (evaluating 'client.app.log')
Cause: OpenCode calls every exported function/value from a plugin file as if it
were a plugin entry point. The file had export function logWarn(client, ...) and
export async function withTimeout(...) — OpenCode called logWarn(ctx) where
ctx is the PluginInput object, binding client = ctx. Since ctx has no .app
property, client.app.log throws.
Fix: Remove export from all utility functions — only BackgroundAgents and
export default should be exported.
Operating System
Windows
Agent / Client
OpenCode
Shell
Other
📋 Relevant Logs
2026-03-17T19:51:41Z service=plugin error=Cannot call a class constructor TimeoutError without |new| failed to load plugin
2026-03-17T20:02:35Z service=plugin error=undefined is not an object (evaluating 'client.app.log') failed to load plugin
💡 Additional Context
Both fixes are minimal and non-breaking. The root cause of Error 2 is an undocumented
behavior of OpenCode's plugin loader: it iterates all named exports and attempts to
invoke each one as a plugin. Plugin files should only export the plugin function itself.
📋 Pre-flight Checks
status:approvedbefore a PR can be opened📝 Bug Description
The background-agents.ts plugin fails to load entirely on OpenCode Desktop 1.2.27. Two separate errors occur in sequence, each preventing the plugin from initializing.
🔄 Steps to Reproduce
✅ Expected Behavior
The plugin loads successfully and registers the delegate, delegation_read, and delegation_list tools.
❌ Actual Behavior
Two sequential errors in the sidecar logs:
Error 1:
service=plugin error=Cannot call a class constructor TimeoutError without |new|
Cause: OpenCode's plugin bundler transpiles ES6 class syntax to functions. When
TimeoutError extends Error is transpiled, calls to
new TimeoutError(...)insidePromise.race() lose the
newkeyword, crashing the constructor.Fix: Replace the class with an interface + factory function:
interface TimeoutError extends Error { readonly name: "TimeoutError"; readonly timeoutMs: number }
function makeTimeoutError(message: string, timeoutMs: number): TimeoutError { ... }
function isTimeoutError(e: unknown): e is TimeoutError { return e instanceof Error && (e as any).name === "TimeoutError" }
Error 2 (after fixing Error 1):
service=plugin error=undefined is not an object (evaluating 'client.app.log')
Cause: OpenCode calls every exported function/value from a plugin file as if it
were a plugin entry point. The file had
export function logWarn(client, ...)andexport async function withTimeout(...)— OpenCode calledlogWarn(ctx)wherectxis the PluginInput object, bindingclient = ctx. Sincectxhas no.appproperty,
client.app.logthrows.Fix: Remove
exportfrom all utility functions — onlyBackgroundAgentsandexport defaultshould be exported.Operating System
Windows
Agent / Client
OpenCode
Shell
Other
📋 Relevant Logs
💡 Additional Context
Both fixes are minimal and non-breaking. The root cause of Error 2 is an undocumented
behavior of OpenCode's plugin loader: it iterates all named exports and attempts to
invoke each one as a plugin. Plugin files should only export the plugin function itself.