{"record":{"id":"e793a32061014fff","repo":"can1357/oh-my-pi","slug":"no-api-key-available-for-model-model-provider","errorCode":null,"errorMessage":"No API key available for model ${model.provider}/${model.id}","messagePattern":"No API key available for model (.+?)/(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/commit/model-selection.ts","lineNumber":53,"sourceCode":"\t};\n\nexport async function resolvePrimaryModel(\n\toverride: string | undefined,\n\tsettings: Settings,\n\tmodelRegistry: CommitModelRegistry,\n): Promise<ResolvedCommitModel> {\n\tconst available = modelRegistry.getAvailable();\n\tconst matchPreferences = getModelMatchPreferences(settings);\n\tconst resolved = override\n\t\t? resolveModelRoleValue(override, available, { settings, matchPreferences })\n\t\t: resolveRoleSelection([\"commit\", \"smol\", ...MODEL_ROLE_IDS], settings, available);\n\tconst model = resolved?.model;\n\tif (!model) {\n\t\tthrow new Error(\"No model available for commit generation\");\n\t}\n\tconst apiKey = await modelRegistry.getApiKey(model);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key available for model ${model.provider}/${model.id}`);\n\t}\n\treturn {\n\t\tmodel,\n\t\tapiKey: modelRegistry.resolver(model),\n\t\tthinkingLevel: concreteThinkingLevel(resolved?.thinkingLevel),\n\t};\n}\n\nexport async function resolveSmolModel(\n\tsettings: Settings,\n\tmodelRegistry: CommitModelRegistry,\n\tfallbackModel: Model<Api>,\n\tfallbackApiKey: ApiKey,\n): Promise<ResolvedCommitModel> {\n\tconst available = modelRegistry.getAvailable();\n\tconst resolvedSmol = resolveRoleSelection([\"smol\"], settings, available);\n\tif (resolvedSmol?.model) {\n\t\tconst apiKey = await modelRegistry.getApiKey(resolvedSmol.model);","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/commit/model-selection.ts#L35-L71","documentation":"resolvePrimaryModel picks the model used to generate commit messages. After resolving a model it calls modelRegistry.getApiKey(model); if that returns undefined it throws because the commit pipeline cannot authenticate API calls without a credential. This fail-fast guard ensures the commit command never starts a model request it cannot complete.","triggerScenarios":"Calling resolvePrimaryModel (directly or via primary()/primaryModelPromise) when the resolved model has no API key: the provider's key is unset in env/config, auth refresh failed, or modelRegistry.getApiKey was wired to a lookup that misses this provider.","commonSituations":"Running the commit command before ever authenticating with the provider (`omp auth` / login not done for that provider); a renamed or rotated env var (e.g. ANTHROPIC_API_KEY) removed from CI; switching default model to a provider the user never configured; a custom model registry in tests returning no key.","solutions":["Authenticate with the provider of the resolved model (set the provider's API key env var or run the CLI's auth/login flow).","Verify the env var name for the provider is correct and exported in the shell/CI environment (echo $ANTHROPIC_API_KEY etc.).","Select a different model/provider that does have a configured key (model config or --model flag).","If using a custom modelRegistry, fix getApiKey to resolve keys for that provider."],"exampleFix":"// before (CI): commit generation fails\n# no key in environment\n// after\nexport ANTHROPIC_API_KEY=sk-ant-...\n# or in CI secrets config:\nenv:\n  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}","handlingStrategy":"validation","validationCode":"const model = resolved?.model;\nif (!model) throw new Error(\"No model available for commit generation\");\nconst apiKey = await modelRegistry.getApiKey(model);\nif (!apiKey) {\n  // fall back to another configured provider/model instead of throwing\n  console.error(`No API key for ${model.provider}/${model.id}; configure it or pick another model`);\n}","typeGuard":"function hasApiKey(m: { provider: string; id: string } | undefined): m is { provider: string; id: string } {\n  return m !== undefined;\n}","tryCatchPattern":"try {\n  const primary = await resolvePrimaryModel();\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"No API key available\")) {\n    // prompt user to run auth flow or select a different model\n  } else throw err;\n}","preventionTips":["Run the provider auth/login flow once per machine before using commit generation.","Export provider API keys in shell profile and CI secrets; verify with `echo ${PROVIDER}_API_KEY`.","Keep the default model on a provider you actually have credentials for.","In tests, wire modelRegistry.getApiKey to a key-resolution function covering all providers used."],"tags":["authentication","api-key","configuration","cli"],"backgroundTag":"missing-api-key","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}