alibaba/open-code-review · error
bedrock denied access to model %q (%s): %w credentials res
Error message
bedrock denied access to model %q (%s): %w credentials resolved, so this is an authorization gap: the identity needs bedrock:InvokeModel on this model in this region, and the account needs model access enabled for it
What it means
explainError (internal/llm/client.go:1131) is the last Bedrock branch: it matches AccessDenied and IAM's 'not authorized to invoke this API operation' wording — but only after the model-access branch, so reaching here means credentials resolved and account model access is enabled, yet the calling identity's IAM policy lacks bedrock:InvokeModel. The rewrite states this is an authorization gap requiring a policy change, not a console toggle.
Source
Thrown at internal/llm/client.go:1131
" 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 a
// policy change, not a console toggle.
case strings.Contains(msg, "AccessDenied"),
strings.Contains(msg, "not authorized to invoke this API operation"):
return fmt.Errorf("bedrock denied access to model %q (%s): %w\n"+
" credentials resolved, so this is an authorization gap: the identity needs bedrock:InvokeModel on this model in this region, and the account needs model access enabled for it", model, where, err)
}
// Everything else — ValidationException on max_tokens, a network reset, a
// throttle — keeps the service's own wording. Guessing at a cause here would
// send people after the wrong problem, which is the failure this function
// exists to prevent.
return fmt.Errorf("bedrock request failed (%s): %w", where, err)
}
func listProfilesRegionArg(region string) string {
if region == "" {
return ""
}
return " --region " + region
}
// anthropicThinkingBudgetTokens extracts budget_tokens from an
// extra_body.thinking map. Returns ok=false for unrecognized shapes.View on GitHub (pinned to 5cf97d0d15)
Solutions
- Attach an IAM policy granting bedrock:InvokeModel (and InvokeModelWithResponseStream) on the model/inference-profile ARNs in that region
- If Resources are enumerated, add the missing model ARN and cross-region inference profile ARNs (us.anthropic.*, etc.)
- Check for a permissions boundary or SCP denying bedrock:InvokeModel and get it adjusted
- Verify with the IAM Policy Simulator or `aws iam simulate-principal-policy` for the exact action and ARN
Example fix
// before
{"Effect":"Allow","Action":"bedrock:InvokeModel","Resource":"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-*"} # new model not matched
// after
{"Effect":"Allow","Action":["bedrock:InvokeModel","bedrock:InvokeModelWithResponseStream"],"Resource":["arn:aws:bedrock:*::foundation-model/anthropic.*","arn:aws:bedrock:*:<acct>:inference-profile/us.anthropic.*"]} Defensive patterns
Strategy: validation
Validate before calling
out, err := exec.Command("aws", "iam", "simulate-principal-policy",
"--policy-source-arn", roleArn,
"--action-names", "bedrock:InvokeModel",
"--resource-arns", modelArn).Output()
if err != nil || !strings.Contains(string(out), "allowed") {
return fmt.Errorf("%s lacks bedrock:InvokeModel on %s", roleArn, modelArn)
} Try / catch
_, err := cl.Call(ctx, messages)
if err != nil && strings.Contains(err.Error(), "denied access to model") {
return fmt.Errorf("add bedrock:InvokeModel for %s in %s to the calling identity's policy: %w", modelID, region, err)
} Prevention
- Grant bedrock:InvokeModel (and WithResponseStream) on model and inference-profile ARNs to the roles that review code
- When narrowing Resource lists, include region-prefixed inference profile ARNs (us.anthropic.*)
- Check permissions boundaries and SCPs for bedrock denies when onboarding new accounts
- Run the IAM Policy Simulator after policy changes before deploying
When it happens
Trigger: InvokeModel on a bedrock-runtime endpoint where the authenticated role/user's IAM policy lacks bedrock:InvokeModel (or bedrock:InvokeModelWithResponseStream) for that model ID/region, or a scoped-down Resource element excludes the model/inference-profile ARN.
Common situations: Deployed CI role with an S3-only policy used for reviews; wildcard model ARN replaced with a narrowed one that misses the new model; SCP or permission boundary stripping InvokeModel; inference-profile ARN not covered by the policy's Resource list.
Related errors
- llm.protocol cannot be %q: bedrock derives its host from aws
- %s does not apply to provider %q: aws_region and aws_profile
- bedrock: could not load AWS configuration: %w bedrock uses
- bedrock: no AWS region resolved set AWS_REGION, or give th
- bedrock rejected the token in AWS_BEARER_TOKEN_BEDROCK (%s):
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/1ffff739e6631302.
Report an issue: GitHub.