alibaba/open-code-review · error

provider %q has no api_key or api_key_cmd configured and no

Error message

provider %q has no api_key or api_key_cmd configured and no environment variable fallback found

What it means

Endpoint resolution requires a credential: a static `api_key`, an `api_key_cmd` command that produces one, or a preset provider's environment-variable fallback (e.g. ANTHROPIC_API_KEY). The only exception is ambient-auth providers (e.g. bedrock), where requests are SigV4-signed from the environment's own AWS credential chain. This error fires before api_key_cmd is executed, so it means the config is empty of all credential sources for a non-ambient provider.

Source

Thrown at internal/llm/resolver.go:482

	}

	// Ambient auth follows the protocol actually in force, which is why this is
	// resolved after the override above rather than read off the preset. A preset
	// declares ambient auth (AmbientAuth), but an entry may override the preset's
	// protocol: a bedrock preset switched to "openai" speaks a protocol with no
	// SigV4 signing and needs a token like anything else. Conversely an entry
	// that selects the bedrock protocol explicitly signs its requests whatever
	// the preset says.
	ambientAuth := protocol == ProtocolAnthropicBedrock ||
		(isPreset && preset.AmbientAuth && entry.Protocol == "")

	// No credential at all is an error, and it is reported before api_key_cmd
	// runs: only the command's *execution* is deferred, not the emptiness check.
	// An ambient-auth provider is the exception — it has no key to configure,
	// since credentials come from the environment's own chain and the request is
	// signed rather than bearing a token.
	if apiKey == "" && apiKeyCmd == "" && !ambientAuth {
		return ResolvedEndpoint{}, false, fmt.Errorf("provider %q has no api_key or api_key_cmd configured and no environment variable fallback found", cfg.Provider)
	}

	if cfg.Model != "" {
		model = cfg.Model
	}
	if entry.Model != "" {
		model = entry.Model
	}

	// Build available model list for validation.
	var availableModels []string
	if isPreset {
		availableModels = append(availableModels, preset.Models...)
	}
	availableModels = append(availableModels, entry.Models...)

	// A preset's Models list doubles as an allowlist for --model. For an
	// ambient-auth provider it cannot: Bedrock identifiers are scoped to an

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Set api_key in the provider entry in the ocr config file
  2. Or set api_key_cmd to a command that prints the key (e.g. a secrets-manager CLI)
  3. For preset providers, export the expected env var (e.g. export ANTHROPIC_API_KEY=sk-...) in the shell/service environment
  4. If using AWS Bedrock, set protocol to anthropic-bedrock (or use a bedrock preset without a protocol override) so ambient AWS auth applies

Example fix

// before
[providers.deepseek]
protocol = "openai"
url = "https://api.deepseek.com"

// after
[providers.deepseek]
protocol = "openai"
url = "https://api.deepseek.com"
api_key_cmd = "op read 'op://Vault/deepseek/key'"
Defensive patterns

Strategy: validation

Validate before calling

// Go: pre-flight credential check before invoking ocr
func hasCredential(apiKey, apiKeyCmd, envVar string) error {
	if strings.TrimSpace(apiKey) != "" || strings.TrimSpace(apiKeyCmd) != "" {
		return nil
	}
	if envVar != "" && strings.TrimSpace(os.Getenv(envVar)) != "" {
		return nil
	}
	return fmt.Errorf("no credential: set api_key, api_key_cmd, or %s", envVar)
}

Type guard

func credentialConfigured(apiKey, apiKeyCmd string, envVars ...string) bool {
	if strings.TrimSpace(apiKey) != "" || strings.TrimSpace(apiKeyCmd) != "" {
		return true
	}
	for _, e := range envVars {
		if strings.TrimSpace(os.Getenv(e)) != "" {
			return true
		}
	}
	return false
}

Try / catch

ep, ok, err := resolver.TryProviderConfig(cfg, "")
if err != nil && strings.Contains(err.Error(), "no api_key or api_key_cmd") {
	fmt.Fprintln(os.Stderr, "credential missing; run 'ocr config' or export the provider's API key env var")
	os.Exit(2)
}

Prevention

When it happens

Trigger: Resolving a provider entry where: api_key is empty/whitespace, api_key_cmd is empty/whitespace, no preset env var is set in the environment (custom providers get no env fallback at all), and the effective protocol is not bedrock/ambient-auth.

Common situations: Fresh checkout where the API key env var was never exported; running under CI/systemd where the interactive shell env is absent; using a custom provider (no env fallback exists by design) without a key; whitespace-only api_key values which are deliberately treated as unset.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/d14e3c9acc451d9e. Report an issue: GitHub.