{"record":{"id":"00498c795da3e477","repo":"JuliusBrussee/caveman","slug":"caveman-code-model-must-use-provider-model-format","errorCode":null,"errorMessage":"caveman-code: model must use provider/model format","messagePattern":"caveman-code: model must use provider/model format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/code.ts","lineNumber":551,"sourceCode":"      exitCode = code;\n      finish();\n    });\n    // `close` waits for stdio EOF, which a surviving background descendant never\n    // gives. `exit` is the command's own answer, so the run settles on it with\n    // whatever output arrived rather than waiting on a process it does not own.\n    child.once(\"exit\", (code) => {\n      exitCode = code;\n      setTimeout(finish, EXIT_FLUSH_GRACE_MS).unref();\n    });\n  });\n}\n\nfunction resolveCodingModelID(explicit: string | undefined): string {\n  const requested = explicit ?? process.env.CAVE_MODEL;\n  if (requested !== undefined && requested !== \"\") {\n    const slash = requested.indexOf(\"/\");\n    if (slash <= 0 || slash === requested.length - 1) {\n      throw new Error(\"caveman-code: model must use provider/model format\");\n    }\n    return requested;\n  }\n  const configured: string[] = [];\n  if (process.env.ANTHROPIC_API_KEY) configured.push(\"anthropic/claude-sonnet-4-6\");\n  if (process.env.OPENAI_API_KEY) configured.push(\"openai/gpt-5.5\");\n  if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {\n    configured.push(\"google/gemini-2.5-pro\");\n  }\n  if (configured.length !== 1) {\n    throw new Error(\n      configured.length === 0\n        ? \"caveman-code: no supported provider credential found; set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY\"\n        : \"caveman-code: multiple provider credentials found; set CAVE_MODEL to pick one\",\n    );\n  }\n  return configured[0]!;\n}","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/code.ts#L533-L569","documentation":"resolveCodingModelID requires an explicit model (or CAVE_MODEL env var) to be in 'provider/model' form, e.g. 'anthropic/claude-sonnet-4-6'. It throws when the value has no '/', starts with '/', or ends with '/'.","triggerScenarios":"Setting CAVE_MODEL to 'claude-sonnet-4-6' (missing provider prefix), '/openai/gpt-5.5' (leading slash), or 'openai/' (trailing slash); passing an explicit model argument in any of those malformed shapes.","commonSituations":"Copying a model name from a provider console without the provider prefix; CAVE_MODEL exported from shell config with a shorthand name; trailing slash typo from templated config strings.","solutions":["Set CAVE_MODEL to provider/model format, e.g. 'anthropic/claude-sonnet-4-6'","Pass the explicit model option in provider/model format instead of relying on env","Unset CAVE_MODEL to let the library auto-pick from available provider credentials"],"exampleFix":"// before\nexport CAVE_MODEL=claude-sonnet-4-6\n// after\nexport CAVE_MODEL=anthropic/claude-sonnet-4-6","handlingStrategy":"validation","validationCode":"const model = process.env.CAVE_MODEL;\nif (model && !/^[^/]+\\/[^/]+$/.test(model)) {\n  throw new Error(`CAVE_MODEL must be provider/model, got: ${model}`);\n}","typeGuard":"const isProviderModel = (m: string): boolean => {\n  const i = m.indexOf(\"/\");\n  return i > 0 && i < m.length - 1;\n};","tryCatchPattern":"try {\n  await run({ model: process.env.CAVE_MODEL });\n} catch (err) {\n  if ((err as Error).message.includes(\"provider/model format\")) {\n    throw new Error(`Fix CAVE_MODEL (got \"${process.env.CAVE_MODEL}\"); e.g. anthropic/claude-sonnet-4-6`);\n  } else throw err;\n}","preventionTips":["Always write model IDs as provider/model, never bare model names","Validate CAVE_MODEL in shell startup or CI before invoking the tool","Copy model IDs from the library's documented defaults (e.g. anthropic/claude-sonnet-4-6)"],"tags":["config","env","format-validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}