Skip to content

Plugin system: undefined agent/command crashes, silent prompt_async errors, config hook isolation, hook timing, startup ordering #18310

@ryanskidmore

Description

@ryanskidmore

Description

Several robustness gaps in the plugin system and session prompt paths cause crashes, silent errors, or unexpected behavior when building plugins:

  1. Agent/command resolution crashes with TypeError on invalid namesAgent.get() and Command.get() return undefined for unknown names, but callers at 5 sites in session/prompt.ts dereference without null checks. This produces an untyped TypeError: Cannot read properties of undefined instead of a helpful typed error.

  2. prompt_async route silently drops errors — The /:sessionID/prompt_async route calls SessionPrompt.prompt() without .catch(), so failures in detached prompts are silently lost with no logging and no Session.Event.Error published.

  3. Plugin config hook errors crash entire bootstrap — A single plugin's config hook throwing prevents all subsequent hooks from running. There is no error isolation between hooks in Plugin.init().

  4. command.execute.before hook receives merged parts — The hook fires after template parts are already merged with input.parts, making it difficult for plugins to cleanly replace or transform template content without fragile index-based manipulation.

  5. Plugins added by config hooks not loaded in same startup pass — When a plugin's config hook adds entries to config.plugin, the newly referenced plugins are not loaded because Plugin.state() has already resolved and is cached via Instance.state().

Plugins

N/A — affects core plugin infrastructure, not a specific plugin.

OpenCode version

v1.2.27 (current dev branch)

Steps to reproduce

  1. Call SessionPrompt.prompt({ agent: "nonexistent" }) → crashes with TypeError: Cannot read properties of undefined (reading 'model') instead of a typed error
  2. Trigger a model/agent mismatch error via the prompt_async route → caller sees no error; nothing logged, no Session.Event.Error published
  3. Install a plugin whose config hook throws → all subsequent plugin config hooks are skipped entirely
  4. Register a command.execute.before hook and inspect output.parts → contains both template parts and caller-provided input.parts already merged
  5. In a plugin's config hook, push a new plugin path to config.plugin → the added plugin is not loaded during that startup pass

Screenshot and/or share link

No UI changes — these are internal plugin/session API issues.

Operating System

All platforms (macOS, Linux, Windows)

Terminal

All terminals — not terminal-specific

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions