{"record":{"id":"2ea1487c18200309","repo":"can1357/oh-my-pi","slug":"no-api-key-for-model-provider-model-id-2ea148","errorCode":null,"errorMessage":"No API key for ${model.provider}/${model.id}","messagePattern":"No API key for (.+?)/(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/session/model-controls.ts","lineNumber":226,"sourceCode":"\t\t\tif (!resolved.explicitThinkingLevel || resolved.thinkingLevel === undefined || !resolved.model) continue;\n\t\t\tif (modelsAreEqual(resolved.model, model)) return resolved.thinkingLevel;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tasync setModel(\n\t\tmodel: Model,\n\t\trole: string = \"default\",\n\t\toptions?: {\n\t\t\tselector?: string;\n\t\t\tthinkingLevel?: ThinkingLevel;\n\t\t\tpersist?: boolean;\n\t\t},\n\t): Promise<{ switched: boolean }> {\n\t\tconst previousEditMode = this.#host.resolveActiveEditMode();\n\t\tif (!this.#host.modelRegistry.hasConfiguredAuth(model)) {\n\t\t\tthrow new Error(`No API key for ${model.provider}/${model.id}`);\n\t\t}\n\n\t\tconst targetModel = await this.#host.modelRegistry.refreshSelectedModelMetadata(model);\n\n\t\tthis.#host.modelRegistry.clearSuppressedSelector(formatModelStringWithRouting(targetModel));\n\t\tthis.#host.clearActiveRetryFallback();\n\t\tawait this.#host.setModelWithProviderSessionReset(targetModel);\n\t\tthis.#host.sessionManager.appendModelChange(`${targetModel.provider}/${targetModel.id}`, role);\n\t\tif (options?.persist) {\n\t\t\tthis.#host.settings.setModelRole(\n\t\t\t\trole,\n\t\t\t\tformatRoleModelValue(\n\t\t\t\t\tthis.#host.settings,\n\t\t\t\t\tthis.#host.modelRegistry,\n\t\t\t\t\trole,\n\t\t\t\t\ttargetModel,\n\t\t\t\t\toptions.selector,\n\t\t\t\t\toptions.thinkingLevel,","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/model-controls.ts#L208-L244","documentation":"ModelControls.setModel refuses to switch the session's model when the model registry has no configured authentication for the target model (hasConfiguredAuth(model) is false). This guards the persistent model switch so a turn never starts against a provider the user cannot authenticate to. The message names the provider/model that lacks a key.","triggerScenarios":"Calling setModel({ model, ... }) (directly or via applyRoleModel) with a Model whose provider has no API key / auth configured in the registry.","commonSituations":"Selecting a model from a provider that was never configured (no env var like ANTHROPIC_API_KEY, no models.json auth entry, no logged-in provider); switching roles to a model on an unconfigured provider; key was removed or expired from config before the switch.","solutions":["Configure auth for the target provider (set its API key env var or add credentials via `omp` auth/config) before switching","Pick a different model on a provider that already has configured auth","Check hasConfiguredAuth(model) on the registry before calling setModel","If auth should exist, verify the correct provider profile/config file is loaded and the key is present in the environment"],"exampleFix":"// before\nawait controls.setModel({ model: anthropicModel }); // throws if no key\n// after\nif (host.modelRegistry.hasConfiguredAuth(anthropicModel)) {\n  await controls.setModel({ model: anthropicModel });\n} else {\n  await controls.setModel({ model: fallbackModel });\n}","handlingStrategy":"validation","validationCode":"if (!session.modelRegistry.hasConfiguredAuth(model)) {\n  console.warn(`Skipping ${model.provider}/${model.id}: no API key configured`);\n  return;\n}\nawait controls.setModel({ model });","typeGuard":null,"tryCatchPattern":"try {\n  await controls.setModel({ model });\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"No API key for\")) {\n    // prompt user to configure provider auth or pick another model\n  } else throw err;\n}","preventionTips":["Configure all providers you plan to switch to before the session starts","Filter model pickers/lists with hasConfiguredAuth","Validate keys exist in env/config during startup","Centralize model selection behind an auth-checked helper"],"tags":["api-key","auth","model-switch","configuration"],"backgroundTag":"missing-api-key","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}