Why is my access denied on s3 using the aws-sdk for Node.js?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
An S3 AccessDenied error from the AWS SDK for Node.js almost never means "the SDK is broken." It means the caller identity, the bucket policy, the object policy surface, or encryption requirements do not allow the requested action.
First: Identify Who the SDK Is Calling As
Before reading bucket policies for an hour, confirm the AWS identity your code is actually using:
This is the fastest sanity check in AWS troubleshooting. If the process is running as the wrong IAM user or role, every later S3 policy investigation becomes misleading.
Common Permission Gaps
The most common missing permissions are:
- '
s3:GetObjectfor reading objects' - '
s3:PutObjectfor writing objects' - '
s3:ListBucketfor listing bucket contents' - KMS permissions when the object uses SSE-KMS
Also remember that bucket-level and object-level permissions are different resources. For example, listing a bucket and fetching an object require different ARNs.
Example IAM policy snippet:
If one of those ARNs is wrong, access can still be denied even though the policy "looks" correct at a glance.
Node.js SDK Example
If this throws AccessDenied, the next step is not to rewrite the SDK call. The next step is to inspect the permissions and the identity behind the call.
Bucket Policies Can Override Identity Permissions
Even if the IAM role says "Allow," a bucket policy or an explicit deny elsewhere can still block access. AWS authorization evaluation combines:
- identity policies
- bucket policies
- ACLs in older setups
- block public access settings
- organization-level controls in some environments
An explicit deny wins over an allow.
Encryption Can Cause Surprise Denials
If the bucket or object uses SSE-KMS, S3 access alone may not be enough. The caller may also need KMS permissions such as kms:Decrypt or kms:Encrypt on the relevant key.
This is a common trap because the error still surfaces as an S3 access problem even though the missing permission is on KMS.
Other Easy-to-Miss Causes
- wrong bucket region
- requesting the wrong account's bucket
- object ownership or ACL issues in cross-account uploads
- session credentials expired
- a policy condition such as required VPC endpoint, IP range, or encryption header
Those are all normal causes of AccessDenied and none of them are solved by changing JavaScript syntax.
Common Pitfalls
The biggest mistake is checking only the IAM role attached to the app and assuming that is the whole story. S3 authorization often involves both identity and bucket-side policy layers.
Another mistake is forgetting ListBucket when calling list APIs. A role that can GetObject may still be denied when listing.
A third issue is ignoring KMS. If the object is encrypted with a KMS key, S3 permissions alone may still fail.
Summary
- '
AccessDeniedusually means an AWS authorization mismatch, not an SDK bug.' - Verify the caller identity first with STS.
- Check both bucket-level and object-level S3 permissions.
- Inspect bucket policies, explicit denies, and block-public-access settings.
- If SSE-KMS is involved, include the required KMS permissions too.

