fix(cli): always dispose instance on error to prevent hanging; add friendly ProviderModelNotFoundError/InitError messages\n\n- Wrap bootstrap callback in try/finally to guarantee Instance.dispose()\n- Format provider/model errors into actionable guidance (opencode models, config)\n\nRepro: running `opencode run --model typo/claude-haiku-4-5` prints stack and hangs until SIGINT due to lingering watchers.\nFix: disposing Instance tears down watchers/subscriptions, allowing process to exit.\n\nNotes: Prior attempt (#3083) explicitly exited; this approach addresses root cause without forcing exit and improves UX for common misconfigurations.
parent
1a6fd018f6
commit
d554e7aaef
|
|
@ -6,9 +6,13 @@ export async function bootstrap<T>(directory: string, cb: () => Promise<T>) {
|
|||
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()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}` : "")
|
||||
|
|
|
|||
Loading…
Reference in New Issue