IAM authorization errors
Look up an AccessDenied or trust-policy error by its text. Each entry gives the meaning, ranked causes with the check for each, the fix, and what to do when none fits.
markdownreferencev44FA8-31XJstage: operatetrust: officialtrust: fieldservice: iamservice: organizationsinterface: anyAccessDeniednot authorized to performexplicit denyimplicit denyInvalid principal in policyMalformedPolicyDocumentSCPRCPpermissions boundarysession policytrust policy
Read the end of the message first. It names the policy type that refused the request, and on newer messages the ARN of the exact policy. because no … policy allows means nothing granted it (implicit deny: add an Allow). with an explicit deny in … means a Deny statement matched (find and narrow the Deny). Only one policy type is named even when several refused, and some services do not use this format at all, so a fix for the named type can still leave the request denied.
Most messages follow this shape, where <context> is one of the phrases in the entries below:
User: <principal ARN> is not authorized to perform: <action> on resource: <resource ARN> <context>
The on resource: part is sometimes absent.
because no identity-based policy allows the <action> action
Means: no policy attached to the calling user or role grants this action on this resource.
Causes, most likely first:
- The action is not in any Allow. Check: list the policies attached to the principal named in the message and search them for the action, including wildcards such as
s3:*. - The Allow exists but its
Resourcedoes not match. Check: compare the resource ARN in the message, character for character, with the policy'sResource. Bucket-level and object-level S3 ARNs are different resources. - The Allow exists but a
Conditionis not met. Check: read every condition key in the statement and confirm the request carries it. Condition key names are not case-sensitive, so two request keys differing only by case can make the condition behave unexpectedly. - Wrong principal. The message names the identity that actually made the call. Check:
aws sts get-caller-identity. If it is not the identity you expected, the credentials came from somewhere else; seereference/sts/credential-sources.md.
Check without making the call: iam:SimulatePrincipalPolicy (CLI aws iam simulate-principal-policy) with PolicySourceArn, ActionNames and ResourceArns. It does not run the action. It evaluates SCPs but does not support RCPs, and it does not fetch resource-based policies for you; pass one in ResourcePolicy.
Fix: add or correct an Allow statement for the action and resource in an identity-based policy attached to the principal.
because no resource-based policy allows the <action> action
Means: the resource's own policy (bucket policy, secret policy, key policy, queue policy) does not grant this principal the action.
Causes, most likely first:
- The request is cross-account. Across accounts both sides must allow: the caller's identity policy in its account and the resource policy in the resource's account. Check: compare the account ID in the principal ARN with the one in the resource ARN.
- The resource policy's
Principaldoes not match the caller. Check: an assumed-role session is not the same string as the role ARN; compare with the principal ARN in the message.
Fix: add a statement to the resource policy naming the caller (or its account) as Principal and allowing the action.
because no service control policy allows the <action> action
Means: an AWS Organizations SCP on the account, or on an organizational unit above it, does not allow the action. SCPs limit: an SCP Allow is necessary for access but never sufficient on its own.
Check: with access to the organization's policies, list the SCPs attached to the root, every OU in the direct path, and the account itself. An explicit Allow must exist at every one of those levels; a missing Allow at any level blocks every account beneath it.
Fix: an organization administrator adds the action to the SCPs in the path. You cannot fix this from inside the member account.
because no permissions boundary allows the <action> action
Means: the principal has a permissions boundary, and the boundary does not include the action, even though the identity policy may allow it. Boundaries do not limit what a resource-based policy grants.
Fix: add the action to the boundary policy, or ask whoever owns the boundary to.
because no session policy allows the <action> action
Means: the credentials came from AssumeRole (or a federation call) with a session policy passed in, and that policy does not allow the action. A session can never have more than the intersection of the role's policies and the session policies.
Fix: request new credentials with a session policy that includes the action, or with none. Adding the action to the role's policies does not help while the session policy excludes it, because the session gets only the intersection of the two.
because no VPC endpoint policy allows the <action> action
Means: the request went through a VPC endpoint whose policy does not allow it. Such denials may not appear in CloudTrail when the endpoint belongs to a different account than the caller or the target role.
Fix: add an Allow for the action to the endpoint policy, or send the request by another route. See patterns/iam-to-vpc-endpoints.md.
because no role trust policy allows the sts:AssumeRole action
Means: the role's trust policy does not name the caller as a principal allowed to assume it.
Causes, most likely first:
- The caller is not in
Principal. Check: read the role's trust policy. - A trust-policy condition is not met, such as MFA (
aws:MultiFactorAuthPresent), an external ID, or a required session name or source identity. Check: read the trust policy'sConditionand compare it with what the call sent. - The caller's own account does not allow
sts:AssumeRoleon the role ARN (cross-account). Check: the caller's identity policies.
Fix: add the caller to the trust policy's Principal, or supply what the condition requires. See patterns/iam/trust-policies.md.
with an explicit deny in a <type> policy (optionally followed by : <policy ARN>)
<type> is one of: service control, resource control, permissions boundary, session, identity-based, resource-based, VPC endpoint. A trust-policy Deny reads with an explicit deny in the role trust policy.
Means: a Deny statement in that policy type matched the request. An explicit deny overrides every Allow.
Causes, most likely first:
- A guardrail Deny is doing its job (an SCP or RCP blocking a Region, a service, or access from outside the organization). Check: if the message includes a policy ARN, read that policy; if not, read every policy of the named type in scope.
- A Deny with conditions matched unexpectedly. Several condition keys in one Deny statement must all match for the Deny to apply; check each key against the request.
- An MFA-enforcement Deny. The common pattern is a Deny with
"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}. The key is absent for requests signed with long-term access keys, so this pattern also denies scripts using access keys. Check: whether the session was created with MFA, and whether the caller uses access keys. - A Deny keyed on caller identity, such as an
aws:useridallow-list or a required VPC endpoint (aws:SourceVpce). Check: whether your caller ID or network path is in the list.
Fix: narrow or remove the Deny, add an exception condition for the principal that needs access, or meet the condition (sign in with MFA, use the required endpoint). For SCPs and RCPs this is an organization administrator's change.
Note on the ARN: AWS began adding the denying policy's ARN to these messages in early 2026, rolling out gradually. It appears only when the caller is in the same account or organization as the policy. It is an identifier only, not the policy's content.
with an explicit deny (no policy type)
Means: the same as the entry above, from a service or a message format that does not name the policy type. Treat every policy type as a suspect: identity-based, resource-based, permissions boundary, session, SCP, RCP and VPC endpoint.
Failed to update trust policy. Invalid principal in policy.
Also appears from the API as MalformedPolicyDocument with Invalid principal in policy.
Means: the trust policy's Principal element has a value IAM cannot accept.
Causes, most likely first:
- A partial wildcard, such as
arn:aws:iam::111122223333:role/deploy-*. Wildcards cannot match part of a principal. Fix: use"*"as the principal with anaws:PrincipalArncondition carrying the pattern. - A deleted principal. If the policy shows an ID beginning
AROA(role) orAIDA(user) instead of an ARN, the entity it named was deleted. Fix: replace it with the ARN of an existing principal. - Wrong format. Accounts need a 12-digit ID or the account root ARN; users and roles need full ARNs; services need the full service principal such as
ec2.amazonaws.com; SAML providers need the provider ARN. Fix: correct the format. - Partition mismatch. A role cannot trust a principal in an AWS GovCloud (US) account from a standard account, or the reverse.
When none of these fits
- Confirm the caller:
aws sts get-caller-identity. - Simulate the decision with
iam:SimulatePrincipalPolicy, passing the resource policy inResourcePolicyif there is one. Remember that it does not evaluate RCPs. - If you sign requests yourself rather than through an SDK, check the signature: a badly signed request can surface as a denial.
- Read
reference/iam/policy-evaluation.mdfor the full order of checks, then followguides/iam/fix-access-denied.mdstep by step. - If the message text matches nothing here, search the hub with the exact text and no
rolefilter; it may come from STS (reference/sts/errors.md) or a service-specific layer. Encoded authorization failure message: decode it first (reference/ec2/errors.md).