Skip to main content
Fix Terraform Error - Error Putting S3 Policy - MalformedPolicy

Fix Terraform Error - Error Putting S3 Policy - MalformedPolicy

Key Takeaway

How to fix MalformedPolicy errors when applying S3 bucket policies in Terraform. Debug JSON syntax, ARN format, and principal issues.

Table of Contents

The Error

Error putting S3 policy: MalformedPolicy: Invalid principal in policy

What Causes This

The S3 bucket policy has invalid JSON, incorrect ARN format, or references a principal that doesn’t exist. This also happens when the policy is too large (20KB limit) or has conflicting statements.

How to Fix It

Solution 1: Use jsonencode Instead of Heredoc

# BAD — heredoc is error-prone
resource "aws_s3_bucket_policy" "public" {
  bucket = aws_s3_bucket.web.id
  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*"
  }]
}
EOF
}

# GOOD — jsonencode catches errors at plan time
resource "aws_s3_bucket_policy" "public" {
  bucket = aws_s3_bucket.web.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "PublicRead"
      Effect    = "Allow"
      Principal = "*"
      Action    = "s3:GetObject"
      Resource  = "${aws_s3_bucket.web.arn}/*"
    }]
  })
}

Solution 2: CloudFront OAC Policy

resource "aws_s3_bucket_policy" "cdn" {
  bucket = aws_s3_bucket.web.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "AllowCloudFront"
      Effect    = "Allow"
      Principal = {
        Service = "cloudfront.amazonaws.com"
      }
      Action    = "s3:GetObject"
      Resource  = "${aws_s3_bucket.web.arn}/*"
      Condition = {
        StringEquals = {
          "AWS:SourceArn" = aws_cloudfront_distribution.cdn.arn
        }
      }
    }]
  })
}

Solution 3: Validate with AWS CLI

# Test the policy before applying
aws s3api put-bucket-policy \
  --bucket my-bucket \
  --policy file://policy.json \
  --dry-run  # Not supported, but you can validate the JSON
  
# Check existing policy
aws s3api get-bucket-policy --bucket my-bucket | python3 -m json.tool

Prevention Tips

  1. Pin provider versions — avoid surprise breaking changes
  2. Use CI/CD — catch errors before they hit production
  3. Test with terraform plan — always review before applying
  4. Keep Terraform updated — newer versions have better error messages
  5. Use terraform validate — catches syntax errors early

Hands-On Courses

Learn to avoid these errors with interactive, project-based courses:

Conclusion

Related: Fix the Terraform inconsistent dependency lock file error — quick fix for this common issue.

This error is common and fixable. Follow the solutions above, and check our Terraform course for hands-on training that covers real-world troubleshooting scenarios.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.