{"record":{"id":"6c8b8f262f056bad","repo":"alibaba/open-code-review","slug":"bedrock-rejected-an-api-key-header-rather-than-a-s","errorCode":null,"errorMessage":"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","messagePattern":"bedrock rejected an API-key header rather than a signature \\((.+?)\\): %w\n  no api_key applies to bedrock; this means a bearer token reached the request, not that a key is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/llm/client.go","lineNumber":1109,"sourceCode":"\tif err == nil || !c.bedrock {\n\t\treturn err\n\t}\n\tmsg := err.Error()\n\twhere := c.bedrockWhere()\n\n\t// Order matters here, and the two AccessDenied shapes are why: Bedrock\n\t// answers both \"your IAM policy forbids this\" and \"this account has not\n\t// enabled the model\" with AccessDeniedException, and the fixes have nothing\n\t// in common. The specific wording is matched before the generic code.\n\tswitch {\n\t// First: the bearer-token path produces this even when credentials are\n\t// otherwise valid, so a later \"denied\" branch would mislabel it.\n\tcase strings.Contains(msg, \"Invalid API Key format\"):\n\t\tif os.Getenv(\"AWS_BEARER_TOKEN_BEDROCK\") != \"\" {\n\t\t\treturn fmt.Errorf(\"bedrock rejected the token in AWS_BEARER_TOKEN_BEDROCK (%s): %w\\n\"+\n\t\t\t\t\"  unset that variable to sign requests with SigV4 instead\", where, err)\n\t\t}\n\t\treturn fmt.Errorf(\"bedrock rejected an API-key header rather than a signature (%s): %w\\n\"+\n\t\t\t\"  no api_key applies to bedrock; this means a bearer token reached the request, not that a key is missing\", where, err)\n\tcase strings.Contains(msg, \"don't have access to the model\"):\n\t\treturn fmt.Errorf(\"bedrock has no access enabled for model %q (%s): %w\\n\"+\n\t\t\t\"  model access is granted per account and per region in the Bedrock console; an IAM policy alone does not enable it\", model, where, err)\n\tcase strings.Contains(msg, \"model identifier is invalid\"),\n\t\tstrings.Contains(msg, \"inference profile\") && strings.Contains(msg, \"not found\"):\n\t\treturn fmt.Errorf(\"bedrock rejected model %q (%s): %w\\n\"+\n\t\t\t\"  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\",\n\t\t\tmodel, where, err, listProfilesRegionArg(c.awsRegion))\n\t// Specific credential codes only. A bare \"expired\" would also claim an\n\t// expired TLS certificate is an SSO problem.\n\tcase strings.Contains(msg, \"ExpiredToken\"), strings.Contains(msg, \"ExpiredTokenException\"),\n\t\tstrings.Contains(msg, \"SSOProviderInvalidToken\"), strings.Contains(msg, \"InvalidGrantException\"),\n\t\tstrings.Contains(msg, \"NoCredentialProviders\"), strings.Contains(msg, \"failed to refresh cached credentials\"):\n\t\treturn fmt.Errorf(\"bedrock could not authenticate: AWS credentials are expired or unavailable (%s): %w\\n\"+\n\t\t\t\"  run `aws sso login%s`, or refresh whichever credential source this profile uses\", where, err, ssoLoginProfileArg(c.awsProfile))\n\t// \"not authorized to invoke this API operation\" is IAM's own wording, so it\n\t// belongs here rather than in the model-access branch above: the fix is a","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/llm/client.go#L1091-L1127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nenv | grep -i bearer   # AWS_BEARER_TOKEN_BEDROCK_API_KEY=abc found (different name, still honored)\n// after\nunset AWS_BEARER_TOKEN_BEDROCK_API_KEY\n# requests now sign with SigV4","handlingStrategy":"type-guard","validationCode":"for _, e := range os.Environ() {\n    if strings.HasPrefix(e, \"AWS_BEARER_TOKEN\") {\n        return fmt.Errorf(\"unexpected %s set — unset it so SigV4 signing is used\", e)\n    }\n}","typeGuard":"func bearerTokenLeaked(env []string) (string, bool) {\n    for _, kv := range env {\n        if strings.HasPrefix(kv, \"AWS_BEARER_TOKEN\") {\n            return kv, true\n        }\n    }\n    return \"\", false\n}","tryCatchPattern":"_, err := cl.Call(ctx, messages)\nif err != nil && strings.Contains(err.Error(), \"rejected an API-key header\") {\n    env, ok := bearerTokenLeaked(os.Environ())\n    if ok { log.Printf(\"token source: %s — unset it\", env) }\n    return err\n}","preventionTips":["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"],"tags":["aws","bedrock","bearer-token","authentication","http-headers"],"backgroundTag":"invalid-bearer-token","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}