{"record":{"id":"9a79ca590ed2df62","repo":"alibaba/open-code-review","slug":"api-key-is-required-for-provider-s-configure-it","errorCode":null,"errorMessage":"API key is required for provider %s (configure it, set providers.%s.api_key_cmd, or set $%s)","messagePattern":"API key is required for provider (.+?) \\(configure it, set providers\\.(.+?)\\.api_key_cmd, or set \\$(.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/provider_cmd.go","lineNumber":252,"sourceCode":"// api_key_cmd -> env var), so an already-configured command satisfies the\n// requirement and picking a model for such a provider does not fail and abandon\n// the save. apiKeyCmd is trimmed because the resolver treats a whitespace-only\n// command as unset, so without this a command of \"   \" would satisfy the check\n// here and then fail resolution with \"no api_key or api_key_cmd configured\".\n//\n// An ambient-auth provider has no credential to save at all: demanding one would\n// make it impossible to configure, since the credentials live in the AWS chain\n// rather than the config file.\nfunc checkAPIKeyRequirement(providerName, apiKey, apiKeyCmd string, preset llm.Provider, isPreset bool) error {\n\tif apiKey != \"\" || strings.TrimSpace(apiKeyCmd) != \"\" {\n\t\treturn nil\n\t}\n\tswitch {\n\tcase isPreset && preset.AmbientAuth:\n\t\treturn nil\n\tcase isPreset && preset.EnvVar != \"\":\n\t\tif os.Getenv(preset.EnvVar) == \"\" {\n\t\t\treturn fmt.Errorf(\"API key is required for provider %s (configure it, set providers.%s.api_key_cmd, or set $%s)\", providerName, providerName, preset.EnvVar)\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"API key is required for provider %s (configure it or set providers.%s.api_key_cmd)\", providerName, providerName)\n\t}\n}\n\nfunc applyOfficialProviderConfig(configPath string, cfg *Config, result providerTUIResult) error {\n\tif result.provider == \"\" {\n\t\treturn fmt.Errorf(\"provider and model are required\")\n\t}\n\tmodel := result.resolvedModel()\n\tif model == \"\" {\n\t\treturn fmt.Errorf(\"provider and model are required\")\n\t}\n\n\tpreset, isPreset := llm.LookupProvider(result.provider)\n","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/provider_cmd.go#L234-L270","documentation":"checkAPIKeyRequirement enforces that an official preset provider has a usable API key before its config is applied. For presets that authenticate via an environment variable (preset.EnvVar, no AmbientAuth), it fails when that env var is unset at config time, telling the user every sanctioned way to supply the key.","triggerScenarios":"Applying an official provider whose preset declares EnvVar (e.g. ANTHROPIC_API_KEY) while os.Getenv(preset.EnvVar) returns \"\" and no api_key/api_key_cmd satisfies the check.","commonSituations":"Fresh machine or CI container where the vendor env var was never exported; env var set in an interactive shell but not in the environment of the ocr process; typo'd env var name; key stored only in a config file field the check does not consult.","solutions":["Export the preset's env var, e.g. export ANTHROPIC_API_KEY=sk-..., then rerun the config command","Configure providers.<name>.api_key_cmd in the config so the key is fetched from a secret manager at runtime","Enter the API key in the provider wizard when prompted","Check that the env var is visible to the ocr process (same shell/session, not just .bashrc)"],"exampleFix":"// before (shell)\nocr config provider   # fails: ANTHROPIC_API_KEY unset\n// after\nexport ANTHROPIC_API_KEY=sk-ant-...\nocr config provider","handlingStrategy":"validation","validationCode":"preset, isPreset := llm.LookupProvider(name)\nif isPreset && !preset.AmbientAuth && preset.EnvVar != \"\" && os.Getenv(preset.EnvVar) == \"\" {\n    // prompt for key or set providers.<name>.api_key_cmd before running config\n}","typeGuard":null,"tryCatchPattern":"if err := run(); err != nil && strings.Contains(err.Error(), \"API key is required for provider\") {\n    fmt.Fprintf(os.Stderr, \"export %s first or configure api_key_cmd\\n\", presetEnvVar)\n    os.Exit(1)\n}","preventionTips":["Export vendor API key env vars in the same shell/session that runs ocr","Configure providers.<name>.api_key_cmd for CI/secret-manager setups","Check `ocr config provider` guidance output naming the exact env var"],"tags":["config","api-key","environment","provider"],"backgroundTag":"missing-env-var","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}