AWS CLI "An error occurred (AccessDenied)" - Fix IAM in CI
AWS authenticated the caller but the IAM policy does not allow the action on that resource. This is authorization, not authentication - the credentials are valid, the permission is missing.
What this error means
An aws command fails with An error occurred (AccessDenied) when calling the <Operation>, naming the action and often the ARN. It is deterministic: the same role fails the same call every time until the policy is fixed.
An error occurred (AccessDenied) when calling the PutObject operation:
User: arn:aws:sts::1234567890:assumed-role/ci-deploy/session is not authorized to
perform: s3:PutObject on resource: "arn:aws:s3:::my-artifacts/build.zip"Common causes
IAM policy missing the action
The role’s policy does not grant the specific action (e.g. s3:PutObject) on the target resource. The error names exactly which action and ARN were denied.
A boundary, SCP, or resource policy blocks it
A permission boundary, an organization SCP, or a resource-based policy (bucket policy, KMS key policy) can deny even when the identity policy allows it.
How to fix it
Grant the exact denied action
Add the named action and resource to the role’s policy - least privilege, scoped to the ARN in the error.
{
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::my-artifacts/*"
}Check boundaries and resource policies
- Confirm the role identity (
aws sts get-caller-identity) is the one you intend. - Use the IAM Policy Simulator or
--debugto see which policy denied the call. - Check permission boundaries, SCPs, and the resource’s own policy (bucket/KMS) for an explicit deny.
How to prevent it
- Scope deploy-role policies to the exact actions and ARNs the pipeline uses.
- Test new permissions with the IAM Policy Simulator before shipping.
- Account for permission boundaries and SCPs in regulated accounts.