S3 Error: “An error occurred (AccessDenied) when calling the PutObject operation: Access Denied”
S3 Error: “An error occurred (AccessDenied) when calling the PutObject operation: Access Denied”
Fix the exact permissions, policy, encryption, and ownership issues that cause S3 uploads to fail with PutObject AccessDenied errors in modern AWS environments
#AWS #AmazonS3 #CloudComputing #DevOps
Problem
You are attempting to upload an object to an Amazon S3 bucket using the AWS CLI, SDK, application code, automation pipeline, or another AWS service, and the upload fails with the following error:
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
This error commonly appears during:
aws s3 cpaws s3 sync- SDK uploads
- Lambda uploads
- CI/CD artifact pushes
- Cross-account uploads
- Automated backups or exports
At first glance, the error looks simple.
In practice, modern S3 uploads pass through multiple layers of authorization and security controls, and any one of them can block the request.
Clarifying the Issue
This error means the caller successfully reached S3, but S3 rejected the upload attempt.
The request was authenticated.
The upload operation itself was denied.
In modern AWS environments, the most common causes include:
- Missing
s3:PutObject - Bucket policy denies
- KMS permission failures
- Object Ownership conflicts
- Explicit denies from SCPs
- Cross-account upload restrictions
- Public Access Block interactions
It is also important to understand the difference between:
- implicit deny
- explicit deny
AWS denies requests by default unless an allow exists.
That is an implicit deny.
An explicit deny is a policy statement that directly blocks the action, and explicit denies always override allows.
This is no longer just an IAM issue.
Modern S3 authorization is a layered system.
Why It Matters
A failed PutObject operation can stop:
- application uploads
- deployment pipelines
- log ingestion
- backups
- media processing
- Lambda workflows
- cross-region automation
In production environments, this error often cascades into secondary failures that appear unrelated until the upload path is investigated.
Key Terms
s3:PutObjectPermission required to upload objects to S3Bucket Policy Resource-based permissions attached to the bucket
Explicit Deny A deny rule that overrides allows
Implicit Deny Default AWS behavior when no allow exists
SSE-KMS Server-side encryption using AWS KMS
Object Ownership S3 ownership model controlling ACL behavior
SCP (Service Control Policy) Organization-level policy control in AWS Organizations
Steps at a Glance
- Verify the caller identity
- Confirm
s3:PutObjectpermissions - Check the bucket policy for denies
- Verify KMS permissions if encryption is enabled
- Check Object Ownership settings
- Test the upload again
Detailed Steps
Step 1. Verify the Caller Identity
First confirm which IAM identity is making the request.
Run:
aws sts get-caller-identity
This immediately tells you:
- IAM user
- assumed role
- account ID
Many AccessDenied investigations fail because engineers troubleshoot the wrong identity.
This is especially common in:
- CI/CD systems
- Lambda execution roles
- local CLI profiles
- temporary session credentials
Step 2. Confirm s3:PutObject Permissions
The caller must have permission to upload objects.
Example IAM policy:
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
A common mistake is using:
"Resource": "arn:aws:s3:::my-bucket"
instead of:
"Resource": "arn:aws:s3:::my-bucket/*"
This matters because:
arn:aws:s3:::my-bucketrefers to the bucket itselfarn:aws:s3:::my-bucket/*refers to the objects inside the bucket
PutObject applies to objects, not the bucket resource.
Common problems include:
- Wrong bucket ARN
- Missing
/* - Policy attached to the wrong role
- Session policy restrictions
If uploading into a prefix, confirm the policy allows that path.
Step 3. Check the Bucket Policy for Denies
Even if IAM allows the upload, the bucket policy may block it.
Look for:
- explicit denies
- account restrictions
- source IP conditions
- VPC endpoint conditions
- encryption enforcement
Example deny pattern:
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
An explicit deny always overrides an allow.
Also remember: if neither the IAM policy nor the bucket policy explicitly allows the request, AWS denies the operation by default.
Review bucket policy conditions carefully for logic that unintentionally matches your request.
Step 4. Verify KMS Permissions if Encryption Is Enabled
If the bucket enforces SSE-KMS encryption, the caller also needs KMS permissions.
Common required permissions include:
kms:Encryptkms:GenerateDataKey
However, IAM permissions alone may not be enough.
The KMS key policy itself must also allow the caller or account to use the key.
This is one of the most common hidden causes of PutObject AccessDenied failures.
Check:
- IAM permissions
- KMS key policy
- bucket encryption settings
in combination.
Step 5. Check Object Ownership Settings
Many older workflows relied on ACL behavior that no longer functions the same way in modern S3 environments.
Review:
- Bucket owner enforced
- Bucket owner preferred
- ACL usage
- cross-account ownership assumptions
Modern S3 deployments increasingly use:
- Object Ownership
- ACL-disabled configurations
Cross-account upload workflows are especially sensitive to these settings.
Also verify whether AWS Organizations SCPs are blocking S3 actions globally.
An SCP explicit deny can override otherwise correct IAM and bucket permissions.
Step 6. Test the Upload Again
After corrections, retry the upload:
aws s3 cp test.txt s3://my-bucket/
If the upload succeeds, confirm:
- encryption behavior
- object ownership
- downstream automation
- application integration
Do not stop at “upload worked once.”
Validate the entire workflow.
Pro Tips
AccessDeniedis often a symptom, not the root cause- KMS failures frequently masquerade as S3 permission failures
- Cross-account uploads are especially sensitive to Object Ownership changes
- SCP explicit denies can silently override otherwise correct IAM permissions
- Always verify the actual runtime role, especially in Lambda and CI/CD systems
- Missing
/*in S3 object ARNs remains one of the most common policy mistakes
Conclusion
The error:
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
usually means the upload request successfully reached S3, but one of the surrounding authorization layers rejected the operation.
In modern AWS environments, successful uploads depend on aligned:
- IAM permissions
- bucket policies
- encryption permissions
- Object Ownership settings
- KMS key policies
- organizational controls
Systematically checking each layer is the fastest path to resolution.
Aaron Rose is a software engineer and technology writer at tech-reader.blog.
Catch up on the latest explainer videos, podcasts, and industry discussions below.
.jpeg)
