Skip to content
Latchkey

AWS S3 sync AccessDenied before CloudFront invalidation in CI

The upload half of an S3-plus-CloudFront deploy failed: "AccessDenied ... PutObject" during aws s3 sync means the CI role cannot write objects to the bucket. The invalidation never runs because the sync exits non-zero first.

What this error means

aws s3 sync fails partway with "upload failed: ... An error occurred (AccessDenied) when calling the PutObject operation: Access Denied", and the pipeline stops before the CloudFront invalidation step.

aws-cli
upload failed: dist/app.js to s3://my-site-bucket/app.js
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

Common causes

The role lacks s3:PutObject on the bucket

The deploy role can list or read but not write, or the bucket policy denies the principal, so each upload is denied.

A bucket policy or SSE/KMS condition blocks the write

A policy requiring a specific encryption header or a KMS key the role cannot use denies PutObject even when the S3 action is allowed.

How to fix it

Grant write and object listing on the bucket

  1. Add s3:PutObject, s3:DeleteObject, and s3:ListBucket for the bucket and its objects.
  2. If SSE-KMS is enforced, grant kms:GenerateDataKey on the key and pass the sse flag.
  3. Re-run the sync, then the invalidation.
IAM policy
{
  "Effect": "Allow",
  "Action": ["s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
  "Resource": [
    "arn:aws:s3:::my-site-bucket",
    "arn:aws:s3:::my-site-bucket/*"
  ]
}

Order sync before invalidate and fail fast

Only invalidate after a clean sync so you never purge a cache for content that did not upload.

Terminal
aws s3 sync ./dist "s3://my-site-bucket" --delete
aws cloudfront create-invalidation --distribution-id "$DISTRIBUTION_ID" --paths "/*"

How to prevent it

  • Grant least-privilege write on exactly the deploy bucket.
  • Match KMS and SSE requirements when the bucket enforces encryption.
  • Run the invalidation only after a successful sync.

Frequently asked questions

What causes "S3 sync "AccessDenied" (upload then invalidate)"?
The deploy role can list or read but not write, or the bucket policy denies the principal, so each upload is denied.
How do I fix S3 sync "AccessDenied" (upload then invalidate)?
Grant write and object listing on the bucket

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card