{"record":{"id":"8985dc7f39e5e6a4","repo":"paperclipai/paperclip","slug":"pi-list-models-failed-detail","errorCode":null,"errorMessage":"`pi --list-models` failed: ${detail}","messagePattern":"`pi --list-models` failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapters/pi-local/src/server/models.ts","lineNumber":131,"sourceCode":"  const result = await runChildProcess(\n    `pi-models-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n    command,\n    [\"--list-models\"],\n    {\n      cwd,\n      env: runtimeEnv,\n      timeoutSec: 20,\n      graceSec: 3,\n      onLog: async () => {},\n    },\n  );\n\n  if (result.timedOut) {\n    throw new Error(\"`pi --list-models` timed out.\");\n  }\n  if ((result.exitCode ?? 1) !== 0) {\n    const detail = firstNonEmptyLine(result.stderr) || firstNonEmptyLine(result.stdout);\n    throw new Error(detail ? `\\`pi --list-models\\` failed: ${detail}` : \"`pi --list-models` failed.\");\n  }\n\n  // Pi outputs model list to stderr, but fall back to stdout for older versions\n  const output = result.stderr || result.stdout;\n  return sortModels(dedupeModels(parseModelsOutput(output)));\n}\n\nfunction normalizeEnv(input: unknown): Record<string, string> {\n  const envInput = typeof input === \"object\" && input !== null && !Array.isArray(input)\n    ? (input as Record<string, unknown>)\n    : {};\n  const env: Record<string, string> = {};\n  for (const [key, value] of Object.entries(envInput)) {\n    if (typeof value === \"string\") env[key] = value;\n  }\n  return env;\n}\n","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapters/pi-local/src/server/models.ts#L113-L149","documentation":"Thrown by discoverPiModels when `pi --list-models` exits non-zero. The detail is the first non-empty line of stderr then stdout, surfacing pi's own error message.","triggerScenarios":"runChildProcess returns exitCode != 0 (not timedOut) for `pi --list-models`; detail = firstNonEmptyLine(stderr) || firstNonEmptyLine(stdout).","commonSituations":"pi not installed or not on PATH; provider auth missing/expired; corrupt pi config; incompatible pi version.","solutions":["Read the detail line for pi's own diagnostic.","Install pi and ensure it is on PATH (or override the command).","Authenticate the pi provider (API key env or pi login).","Run `pi --list-models` in the same env to reproduce and fix."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async function piInstalled(): Promise<boolean> {\n  try { await runChildProcess(\"probe\", \"pi\", [\"--version\"], { timeoutSec: 5, graceSec: 1, onLog: async () => {} }); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await discoverPiModels(input);\n} catch (e) {\n  if (e instanceof Error && /`pi --list-models` failed/.test(e.message)) {\n    // read detail; install/auth pi; non-retryable until fixed\n  }\n  throw e;\n}","preventionTips":["Ensure pi is installed and on PATH.","Authenticate the pi provider before discovery.","Catch in listPiModels (already returns [] on error) for non-fatal listing."],"tags":["pi","models","process-error","discovery"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}