Terraform S3 Access Denied — How to Fix It (2026)
Getting AccessDenied when Terraform tries to read or write your S3 backend? Here's every cause and the exact fix.
Terraform hits S3 Access Denied most often during init (reading state) or apply (writing state). The error looks like this:
Error: Failed to get existing workspaces: S3 bucket does not have versioning enabled
Error: AccessDenied: Access Denied
status code: 403
Here's how to find the cause and fix it.
The 5 Most Common Causes
- IAM user/role doesn't have S3 permissions
- S3 bucket policy blocks the IAM principal
- Wrong region configured
- Bucket doesn't exist or typo in bucket name
- KMS encryption — IAM has S3 access but not KMS decrypt
Fix 1: Check IAM Permissions
Your Terraform runner needs these S3 permissions at minimum for remote state:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketVersioning"
],
"Resource": [
"arn:aws:s3:::your-terraform-state-bucket",
"arn:aws:s3:::your-terraform-state-bucket/*"
]
}
]
}Test quickly:
aws s3 ls s3://your-terraform-state-bucket
aws sts get-caller-identity # confirm which IAM entity is runningFix 2: Check Bucket Policy
Even with the right IAM permissions, a restrictive bucket policy can block access.
aws s3api get-bucket-policy --bucket your-terraform-state-bucketIf the bucket policy has an explicit Deny or doesn't have an Allow for your principal — that's your issue.
Add your IAM role/user to the bucket policy:
{
"Principal": {
"AWS": "arn:aws:iam::123456789:role/terraform-runner-role"
},
"Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::your-terraform-state-bucket",
"arn:aws:s3:::your-terraform-state-bucket/*"
]
}Fix 3: KMS Encryption
If your S3 bucket uses KMS encryption (SSE-KMS), the IAM role also needs KMS permissions:
{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:123456789:key/your-kms-key-id"
}Check if the bucket uses KMS:
aws s3api get-bucket-encryption --bucket your-terraform-state-bucketFix 4: DynamoDB Lock Table
If using DynamoDB for state locking, you also need these permissions:
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789:table/terraform-state-lock"
}Fix 5: Wrong Region
terraform {
backend "s3" {
bucket = "your-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "us-east-1" # must match bucket region
}
}If the bucket is in ap-south-1 but backend says us-east-1 — you get Access Denied.
Check bucket region:
aws s3api get-bucket-location --bucket your-terraform-state-bucketQuick Debug Checklist
# Who am I?
aws sts get-caller-identity
# Can I list the bucket?
aws s3 ls s3://your-bucket
# Can I read a specific key?
aws s3 cp s3://your-bucket/path/terraform.tfstate /tmp/test.tfstate
# Check bucket encryption
aws s3api get-bucket-encryption --bucket your-bucketWork through this list top to bottom — 95% of S3 Access Denied errors are fixed by step 2.
Resources
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Terraform Backend S3 Init Failed — Every Cause and Fix (2026)
terraform init fails with S3 backend errors — access denied, bucket does not exist, state lock issues, wrong region. Here's every cause and the exact fix for each one.
Terraform Error Acquiring the State Lock: Causes and Fix
Terraform state lock errors can block your entire team. Learn why they happen, how to safely unlock state, and how to prevent lock conflicts for good.
AWS ALB 504 Gateway Timeout — Every Cause and Fix (2026)
Your ALB returns 504 Gateway Timeout but the app seems fine. Here's every reason this happens — backend timeouts, keepalive mismatches, health check failures — and exactly how to fix each one.