error aws

AWS AccessDenied Error

Understanding AWS AccessDenied error - the IAM user or role does not have permission to perform the requested action on the resource.

What It Means

The AccessDenied error in AWS indicates that the IAM user, role, or service making the request does not have the necessary permissions to perform the requested action. This is AWS’s equivalent of an HTTP 403 Forbidden and is one of the most common AWS errors.

Common Causes

  • IAM policy doesn’t include the required action
  • Resource-based policy (S3 bucket policy, KMS key policy) denying access
  • Service Control Policy (SCP) in AWS Organizations blocking the action
  • Permissions boundary restricting the effective permissions
  • Session policy limiting assumed role permissions
  • Cross-account access not properly configured
  • S3 bucket has Block Public Access enabled
  • KMS key policy not granting access
  • VPC endpoint policy restricting access

How to Fix

Identify the missing permission

# Check who you are
aws sts get-caller-identity

# Check the exact error message — it often tells you which action was denied
aws s3 ls s3://my-bucket/ 2>&1
# An error occurred (AccessDenied) when calling the ListObjectsV2 operation

# Simulate IAM policies (check what's allowed)
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:user/myuser \
  --action-names s3:ListBucket s3:GetObject \
  --resource-arns arn:aws:s3:::my-bucket

Fix IAM policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}
# Attach the policy to a user or role
aws iam attach-user-policy \
  --user-name myuser \
  --policy-arn arn:aws:iam::123456789012:policy/MyS3Policy

# Or for a role
aws iam attach-role-policy \
  --role-name myRole \
  --policy-arn arn:aws:iam::123456789012:policy/MyS3Policy

Fix S3 bucket policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCrossAccountAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/ExternalRole"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

Debug with CloudTrail

# Find the denied API call in CloudTrail
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=ListObjects \
  --max-results 5

# Check for "errorCode": "AccessDenied" in the results

Fix in application code (boto3)

import boto3
from botocore.exceptions import ClientError

s3 = boto3.client('s3')

try:
    response = s3.get_object(Bucket='my-bucket', Key='file.txt')
except ClientError as e:
    if e.response['Error']['Code'] == 'AccessDenied':
        print("Access denied. Check your IAM permissions.")
        print(f"Verify that your role has s3:GetObject on arn:aws:s3:::my-bucket/*")
    raise
// AWS SDK v3 for JavaScript
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';

const client = new S3Client({ region: 'us-east-1' });

try {
  const response = await client.send(new GetObjectCommand({
    Bucket: 'my-bucket',
    Key: 'file.txt',
  }));
} catch (error) {
  if (error.name === 'AccessDenied') {
    console.error('Check IAM permissions for s3:GetObject');
  }
}