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
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