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

  1. Attach an IAM policy granting bedrock:InvokeModel (and InvokeModelWithResponseStream) on the model/inference-profile ARNs in that region
  2. If Resources are enumerated, add the missing model ARN and cross-region inference profile ARNs (us.anthropic.*, etc.)
  3. Check for a permissions boundary or SCP denying bedrock:InvokeModel and get it adjusted
  4. 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

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


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