diff --git a/packages/opencode/src/cli/bootstrap.ts b/packages/opencode/src/cli/bootstrap.ts index 2114cbc565..d5b646dd5c 100644 --- a/packages/opencode/src/cli/bootstrap.ts +++ b/packages/opencode/src/cli/bootstrap.ts @@ -6,9 +6,13 @@ export async function bootstrap(directory: string, cb: () => Promise) { directory, init: InstanceBootstrap, fn: async () => { - const result = await cb() - await Instance.dispose() - return result + // Ensure we always dispose instance state, even on errors, + // so the CLI does not hang due to lingering watchers/subscriptions. + try { + return await cb() + } finally { + await Instance.dispose() + } }, }) } diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts index 1bc20de323..7a8f40bfe5 100644 --- a/packages/opencode/src/cli/error.ts +++ b/packages/opencode/src/cli/error.ts @@ -1,10 +1,22 @@ import { Config } from "../config/config" import { MCP } from "../mcp" +import { Provider } from "../provider/provider" import { UI } from "./ui" export function FormatError(input: unknown) { if (MCP.Failed.isInstance(input)) return `MCP server "${input.data.name}" failed. Note, opencode does not support MCP authentication yet.` + if (Provider.ModelNotFoundError.isInstance(input)) { + const { providerID, modelID } = input.data + return [ + `Model not found: ${providerID}/${modelID}`, + `Try: \`opencode models\` to list available models`, + `Or check your config (opencode.json) provider/model names`, + ].join("\n") + } + if (Provider.InitError.isInstance(input)) { + return `Failed to initialize provider "${input.data.providerID}". Check credentials and configuration.` + } if (Config.JsonError.isInstance(input)) { return ( `Config file at ${input.data.path} is not valid JSON(C)` + (input.data.message ? `: ${input.data.message}` : "")