How to Fix AWS S3 AccessDenied Error When Calling PutObject
Quick Answer: The S3 AccessDenied error when calling PutObject occurs when your IAM user or role lacks the s3:PutObject permission on the target bucket or object. This can happen due to missing IAM policies, bucket policies that explicitly deny access, or incorrect resource ARNs in your policy. Check your IAM permissions, bucket policy, and object ACL to grant write access.
What Causes This Error
- IAM user or role missing s3:PutObject permission in attached policies
- Bucket policy explicitly denies s3:PutObject action for your principal
- Resource ARN in IAM policy uses incorrect bucket name or object path
- Object ACL restricts write access to the bucket owner only
- Cross-account access without proper trust relationship or resource-based policy
- Session token expired or temporary credentials lack required permissions
- Bucket has versioning enabled and policy restricts s3:PutObjectVersionTagging
- KMS encryption enabled but IAM policy lacks kms:Decrypt and kms:GenerateDataKey permissions
Step-by-Step Fixes
Fix 1: Verify IAM Policy Includes s3:PutObject Permission
Log into AWS Management Console and navigate to IAM > Users or Roles,Select the user or role making the S3 request,Click 'Permissions' tab and review attached policies,Search for 's3:PutObject' in the policy JSON,If missing, click 'Add permissions' > 'Attach policies directly' > select 'AmazonS3FullAccess' or create custom policy with s3:PutObject action,Verify the Resource ARN matches your bucket: 'arn:aws:s3:::bucket-name/*'
Fix 2: Check Bucket Policy for Explicit Deny
Navigate to S3 > Buckets > select your bucket > Permissions tab,Scroll to 'Bucket policy' and click 'Edit',Search for 'Deny' statements targeting s3:PutObject,If found, review the Principal and Condition to determine if it's blocking your IAM user,Remove or modify the Deny statement if it's unintended,Click 'Save changes' to apply the policy update
Fix 3: Verify Resource ARN in IAM Policy
In IAM policy JSON, locate the Resource field under s3:PutObject action,Confirm the ARN format is correct: 'arn:aws:s3:::bucket-name/*' for all objects,If targeting specific prefixes, use: 'arn:aws:s3:::bucket-name/prefix/*',Ensure bucket name matches exactly (case-sensitive),Test with AWS CLI: 'aws s3 cp test.txt s3://bucket-name/test.txt' to verify access
Fix 4: Check Object and Bucket ACLs
Navigate to S3 > Buckets > select bucket > Permissions tab,Check 'Block public access' settings (should be enabled for security),Click on specific object and check its ACL (Object actions > Edit ACL),Ensure the bucket owner has full control,If using object ACL, grant write access to the appropriate principal,For cross-account access, add the external account ID to the ACL
Fix 5: Verify KMS Encryption Permissions (if applicable)
If bucket uses KMS encryption, navigate to KMS > Customer managed keys,Select the KMS key used for encryption,Click 'Key policy' and verify your IAM user/role has kms:Decrypt and kms:GenerateDataKey permissions,If missing, add the following to the key policy: '"Action": ["kms:Decrypt", "kms:GenerateDataKey"]',Ensure the Resource is the KMS key ARN,Save the key policy and retry the S3 PutObject operation
FAQs
Q: How do I test S3 PutObject permissions before running my application?
A: Use the AWS CLI command: 'aws s3 cp test.txt s3://bucket-name/test.txt --region us-east-1'. If you receive AccessDenied, the IAM policy is missing s3:PutObject. If successful, your permissions are correct.
Q: Can I use a bucket policy instead of IAM policy for S3 PutObject?
A: Yes, bucket policies can grant s3:PutObject access. However, IAM policies are recommended for user-level access control. Bucket policies are better for cross-account or public access scenarios. Both must allow the action for successful upload.
Q: What's the difference between s3:PutObject and s3:PutObjectAcl?
A: s3:PutObject allows uploading or overwriting objects. s3:PutObjectAcl allows modifying object access control lists. You may need both permissions depending on your use case.
Q: How do I grant cross-account S3 access for PutObject?
A: Create an IAM role in the target account with s3:PutObject permission. In the source account, create an IAM policy that allows 'sts:AssumeRole' for the target role ARN. The bucket policy must also allow the cross-account principal.
Q: Why does S3 PutObject work in the AWS Console but fail in my application?
A: The console uses your AWS credentials (which may have admin access), while your application likely uses a different IAM user or role with limited permissions. Verify the application's IAM credentials have s3:PutObject permission on the specific bucket.