Skip to content

[BUG]: client.app is undefined when passed to plugins, causing crashes in plugin logging #5793

Closed

Description

@shekohex

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.app is undefined)
  • If _client itself was undefined, error would say evaluating '_client.app'

Reproduction

  1. Create a plugin that calls client.app.log():

    export const MyPlugin = async ({ client }: PluginContext) => {
      // This crashes:
      await client.app.log({ body: { message: "test" } });
    };
  2. 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

  1. Is the client object passed to plugins intended to be a full OpencodeClient instance?
  2. Are sub-clients like app, tui, auth lazily initialized or always available?
  3. Is there a specific lifecycle point after which client.app becomes 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

Activity

  1. github-actions commented on Dec 19, 2025

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if this doesn't address your specific case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions