Repository navigation
Description
Description
When a plugin attempts to use client.app.log() to write to server logs, it crashes with TypeError: undefined is not an object because client.app is undefined, even though the SDK types declare it as a required (non-optional) property.
Environment
| Component | Version |
|---|---|
| OpenCode | 1.0.167 |
| @opencode-ai/plugin | ^1.0.169 |
| @opencode-ai/sdk | ^1.0.169 |
| OS | Linux (glibc) |
| Runtime | Bun 1.3.4 |
Error
TypeError: undefined is not an object (evaluating '_client.app.log')
at log (logger.ts:64:15)
at prepareAntigravityRequest (request.ts:329:9)
at tryEndpointFallbacks (fetch-wrapper.ts:522:83)
Analysis
SDK Type Declaration
In @opencode-ai/sdk, the OpencodeClient class declares app as a required property:
// sdk.gen.d.ts
export declare class OpencodeClient extends _HeyApiClient {
// ...
app: App; // Non-optional
// ...
}SDK Implementation
The implementation shows app is initialized as a class field:
// sdk.gen.js
export class OpencodeClient extends _HeyApiClient {
// ...
app = new App({ client: this._client });
// ...
}Expected Behavior
When a plugin receives client: ReturnType<typeof createOpencodeClient> via PluginInput, the client.app property should always be defined and usable.
Actual Behavior
At runtime, client.app is undefined. The JSC error message format confirms this:
- Error says
evaluating '_client.app.log'(meaning_client.appis undefined) - If
_clientitself was undefined, error would sayevaluating '_client.app'
Reproduction
-
Create a plugin that calls
client.app.log():export const MyPlugin = async ({ client }: PluginContext) => { // This crashes: await client.app.log({ body: { message: "test" } }); };
-
The crash occurs during normal plugin operation, particularly when:
- Plugin is loaded and initialized
- First message works
- Second message triggers the crash (during API request handling)
Questions
- Is the
clientobject passed to plugins intended to be a fullOpencodeClientinstance? - Are sub-clients like
app,tui,authlazily initialized or always available? - Is there a specific lifecycle point after which
client.appbecomes available?
Workaround
Plugins can use optional chaining as a defensive measure:
if (client?.app?.log) {
client.app.log({...});
}However, this shouldn't be necessary if the types declare app as required.
Related
- Plugin experiencing this issue: opencode-google-antigravity-auth
- Original bug report: [BUG]: TypeError: undefined is not an object (evaluating '_client.app.log') crashes on API requests shekohex/opencode-google-antigravity-auth#8
Activity
github-actions commentedon Dec 19, 2025
This issue might be a duplicate of existing issues. Please check:
client.session.summarizehangs forever in Plugin #5449:client.session.summarizehangs forever in Plugin - indicates plugin client methods may not be properly initializedFeel free to ignore if this doesn't address your specific case.
fix(logger): handle undefined client.app with optional chaining
fix(logger): handle undefined client.app with optional chaining
fix(logger): handle undefined client.app with optional chaining