alibaba/open-code-review · error
bedrock rejected an API-key header rather than a signature (
Error message
bedrock rejected an API-key header rather than a signature (%s): %w no api_key applies to bedrock; this means a bearer token reached the request, not that a key is missing
What it means
The fallback half of the 'Invalid API Key format' branch in explainError (internal/llm/client.go:1109). Bedrock answered with an API-key-format rejection, but AWS_BEARER_TOKEN_BEDROCK is NOT set — so a bearer token still reached the request from somewhere else (SDK-managed token, BearerToken provider in the loaded config). The message clarifies that no api_key configuration applies to Bedrock and a token leaked into the request rather than a key being missing.
Source
Thrown at internal/llm/client.go:1109
if err == nil || !c.bedrock {
return err
}
msg := err.Error()
where := c.bedrockWhere()
// Order matters here, and the two AccessDenied shapes are why: Bedrock
// answers both "your IAM policy forbids this" and "this account has not
// enabled the model" with AccessDeniedException, and the fixes have nothing
// in common. The specific wording is matched before the generic code.
switch {
// First: the bearer-token path produces this even when credentials are
// otherwise valid, so a later "denied" branch would mislabel it.
case strings.Contains(msg, "Invalid API Key format"):
if os.Getenv("AWS_BEARER_TOKEN_BEDROCK") != "" {
return fmt.Errorf("bedrock rejected the token in AWS_BEARER_TOKEN_BEDROCK (%s): %w\n"+
" unset that variable to sign requests with SigV4 instead", where, err)
}
return fmt.Errorf("bedrock rejected an API-key header rather than a signature (%s): %w\n"+
" no api_key applies to bedrock; this means a bearer token reached the request, not that a key is missing", where, err)
case strings.Contains(msg, "don't have access to the model"):
return fmt.Errorf("bedrock has no access enabled for model %q (%s): %w\n"+
" model access is granted per account and per region in the Bedrock console; an IAM policy alone does not enable it", model, where, err)
case strings.Contains(msg, "model identifier is invalid"),
strings.Contains(msg, "inference profile") && strings.Contains(msg, "not found"):
return fmt.Errorf("bedrock rejected model %q (%s): %w\n"+
" run `aws bedrock list-inference-profiles%s` to see what this account offers — IDs are account- and region-scoped, and a version suffix such as -v1:0 is invalid for the newer families",
model, where, err, listProfilesRegionArg(c.awsRegion))
// Specific credential codes only. A bare "expired" would also claim an
// expired TLS certificate is an SSO problem.
case strings.Contains(msg, "ExpiredToken"), strings.Contains(msg, "ExpiredTokenException"),
strings.Contains(msg, "SSOProviderInvalidToken"), strings.Contains(msg, "InvalidGrantException"),
strings.Contains(msg, "NoCredentialProviders"), strings.Contains(msg, "failed to refresh cached credentials"):
return fmt.Errorf("bedrock could not authenticate: AWS credentials are expired or unavailable (%s): %w\n"+
" run `aws sso login%s`, or refresh whichever credential source this profile uses", where, err, ssoLoginProfileArg(c.awsProfile))
// "not authorized to invoke this API operation" is IAM's own wording, so it
// belongs here rather than in the model-access branch above: the fix is aView on GitHub (pinned to 5cf97d0d15)
Solutions
- Search the environment for any AWS_BEARER_TOKEN* or token variables: env | grep -i bearer, and unset them
- Check ~/.aws/config for bearer_token or api-key style settings and remove them
- Bypass or reconfigure any proxy that injects Authorization headers toward bedrock-runtime
- Run with AWS_SDK_LOAD_CONFIG inspection / debug logging to see which credential provider supplied the token
Example fix
// before env | grep -i bearer # AWS_BEARER_TOKEN_BEDROCK_API_KEY=abc found (different name, still honored) // after unset AWS_BEARER_TOKEN_BEDROCK_API_KEY # requests now sign with SigV4
Defensive patterns
Strategy: type-guard
Validate before calling
for _, e := range os.Environ() {
if strings.HasPrefix(e, "AWS_BEARER_TOKEN") {
return fmt.Errorf("unexpected %s set — unset it so SigV4 signing is used", e)
}
} Type guard
func bearerTokenLeaked(env []string) (string, bool) {
for _, kv := range env {
if strings.HasPrefix(kv, "AWS_BEARER_TOKEN") {
return kv, true
}
}
return "", false
} Try / catch
_, err := cl.Call(ctx, messages)
if err != nil && strings.Contains(err.Error(), "rejected an API-key header") {
env, ok := bearerTokenLeaked(os.Environ())
if ok { log.Printf("token source: %s — unset it", env) }
return err
} Prevention
- Audit the environment for AWS_BEARER_TOKEN* before Bedrock runs
- Remove bearer-token settings from ~/.aws/config
- Check that no proxy or SDK middleware injects an Authorization header toward bedrock-runtime
- Keep only SigV4 credential sources (profile, SSO, IMDS) configured
When it happens
Trigger: A Bedrock InvokeModel call gets 'Invalid API Key format' while the env var is unset: an SDK BearerToken provider (e.g. from a shared config or another AWS_BEARER_TOKEN_* variable) attached a token to the request, or an intermediate proxy injected an Authorization header the service read as an API key.
Common situations: A wrapper script or IDE terminal exported a bearer token under a different name that the AWS SDK still honors; AWS SDK experimental bearer-token config keys enabled in ~/.aws/config; corporate proxy adding an Authorization header.
Related errors
- bedrock rejected the token in AWS_BEARER_TOKEN_BEDROCK (%s):
- bedrock could not authenticate: AWS credentials are expired
- bedrock request failed (%s): %w
- llm.protocol cannot be %q: bedrock derives its host from aws
- %s does not apply to provider %q: aws_region and aws_profile
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/6c8b8f262f056bad.
Report an issue: GitHub.