Skip to content

Plugins deadlock on startup when calling client.app.log() (v1.4.8 regression) #23147

@ghost91-

Description

@ghost91-

Description

v1.4.8 deadlocks when plugins call client.app.log() during initialization. The TUI renders but never shows the active model.

Plugins

Any plugin using client.app.log() during initialization

OpenCode version

1.4.8, 1.4.9

Steps to reproduce

  1. Save the following as ~/.config/opencode/plugins/my-plugin.ts:
    import type { Plugin, PluginModule } from "@opencode-ai/plugin"
    
    const server: Plugin = async ({ client }) => {
      await client.app.log({
        body: { service: "my-plugin", level: "warn", message: "hello" },
      })
      return {}
    }
    
    export default { id: "my-plugin", server } satisfies PluginModule
  2. Start opencode
  3. TUI renders but hangs before showing the active model

Screenshot and/or share link

No response

Operating System

Arch Linux (irrelevant)

Terminal

Alacritty (irrelevant)

Root Cause

v1.4.8 moved InstanceMiddleware before ControlPlaneRoutes in packages/opencode/src/server/server.ts:

// v1.4.8 (broken)
app: app
  .use(InstanceMiddleware())
  .route("/", ControlPlaneRoutes())
  ...

// v1.4.7 (working)
app: app
  .route("/", ControlPlaneRoutes())
  .route("/", InstanceRoutes(runtime.upgradeWebSocket))
  ...

InstanceMiddleware calls Instance.provide({ init: InstanceBootstrap }) on every request. InstanceBootstrap calls Plugin.init(), which loads all plugins. The deadlock:

  1. InstanceMiddleware runs InstanceBootstrapPlugin.init() → plugin server() runs
  2. Plugin calls client.app.log() → in-process fetch to Hono
  3. Hono routes the request through InstanceMiddleware again
  4. Instance.provide() awaits the same bootstrap promise from step 1
  5. Deadlock: step 4 waits for step 1, which waits for step 2, which waits for step 4

Possibly related: #23103, which may be the same deadlock triggered by a different code path through InstanceMiddleware.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions