{"record":{"id":"0a85ee532f5ece50","repo":"paperclipai/paperclip","slug":"opencode-models-failed-detail","errorCode":null,"errorMessage":"`opencode models` failed: ${detail}","messagePattern":"`opencode models` failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapters/opencode-local/src/server/models.ts","lineNumber":153,"sourceCode":"  const result = await runChildProcess(\n    `opencode-models-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n    command,\n    [\"models\"],\n    {\n      cwd,\n      env: runtimeEnv,\n      timeoutSec: MODELS_DISCOVERY_TIMEOUT_MS / 1000,\n      graceSec: 3,\n      onLog: async () => {},\n    },\n  );\n\n  if (result.timedOut) {\n    throw new Error(`\\`opencode models\\` timed out after ${MODELS_DISCOVERY_TIMEOUT_MS / 1000}s.`);\n  }\n  if ((result.exitCode ?? 1) !== 0) {\n    const detail = firstNonEmptyLine(result.stderr) || firstNonEmptyLine(result.stdout);\n    throw new Error(detail ? `\\`opencode models\\` failed: ${detail}` : \"`opencode models` failed.\");\n  }\n\n  return sortModels(parseOpenCodeModelsOutput(result.stdout));\n}\n\nexport async function discoverOpenCodeModelsCached(input: {\n  command?: unknown;\n  cwd?: unknown;\n  env?: unknown;\n} = {}): Promise<AdapterModel[]> {\n  const command = resolveOpenCodeCommand(input.command);\n  const cwd = asString(input.cwd, process.cwd());\n  const env = normalizeEnv(input.env);\n  const key = discoveryCacheKey(command, cwd, env);\n  const now = Date.now();\n  pruneExpiredDiscoveryCache(now);\n  const cached = discoveryCache.get(key);\n  if (cached && cached.expiresAt > now) return cached.models;","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapters/opencode-local/src/server/models.ts#L135-L171","documentation":"Thrown by discoverOpenCodeModels (LOCAL) when `opencode models` exits non-zero. The detail is the first non-empty line of stderr then stdout, surfacing opencode's own diagnostic. Same shape as the remote failure (389) but for local discovery.","triggerScenarios":"runChildProcess returns exitCode != 0 (not timedOut) for local `opencode models`; detail = firstNonEmptyLine(stderr) || firstNonEmptyLine(stdout).","commonSituations":"opencode not installed / not on PATH on the host (override with PAPERCLIP_OPENCODE_COMMAND); provider auth missing; corrupt opencode config; version incompatibility.","solutions":["Read the detail line — it carries opencode's error (e.g. 'command not found', auth error).","Install opencode or point PAPERCLIP_OPENCODE_COMMAND at the binary.","Authenticate the provider on the host (opencode login or API key env).","Run `opencode models` in the same shell/env to reproduce and fix."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async function openCodeInstalled(): Promise<boolean> {\n  try { await runChildProcess(\"probe\", \"opencode\", [\"--version\"], { timeoutSec: 5, graceSec: 1, onLog: async () => {} }); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await discoverOpenCodeModels(input);\n} catch (e) {\n  if (e instanceof Error && /`opencode models` failed/.test(e.message)) {\n    // surface the detail to the operator; check PATH/PAPERCLIP_OPENCODE_COMMAND and provider auth; non-retryable config issue\n  }\n  throw e;\n}","preventionTips":["Ensure opencode is on PATH or set PAPERCLIP_OPENCODE_COMMAND.","Authenticate providers on the host before discovery.","Catch in listOpenCodeModels (which already returns [] on error) for non-fatal listing."],"tags":["opencode","models","local","process-error","discovery"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}