AccessDeniedException

AWS Lambda Permission Denied: 3 Common Causes & Fixes

Server & Cloud Intermediate 👁 6 views 📅 Jun 17, 2026

Lambda throwing permission denied? Usually it's the IAM role, resource policy, or VPC config. Here's exactly what to check in order.

1. The Execution Role Lacks Permissions for the Target Service

This is the most common reason — by a lot. Your Lambda function needs an IAM execution role with permissions to call whatever service it's hitting. If you're seeing AccessDeniedException when your function tries to write to S3, read from DynamoDB, or publish to SNS, it's almost always the role.

Here's the real-world scenario: You copy-paste a Lambda function from a blog post and forget to attach the right policy. Or you update a role but don't wait for IAM propagation. I've seen both bite people.

I once spent 45 minutes chasing a DynamoDB permission denied error — turns out the role had full DynamoDB access but the function was running in a different region. Yes, that matters.

Fix it:

  1. Go to the IAM console, find your Lambda's execution role.
  2. Click "Add permissions" → "Attach policies". Attach the AWS managed policy for the service you're calling — for example, AmazonS3FullAccess or AmazonDynamoDBFullAccess.
  3. If your function calls multiple services, create a custom policy with only the actions it needs. Least privilege is the goal, but for a quick fix, start broad.

Still stuck? Check this: Does your function call sts:AssumeRole? That's a common hidden permission. Add this to the role:

{
  "Effect": "Allow",
  "Action": "sts:AssumeRole",
  "Resource": "*"
}

Also wait 10 seconds after attaching a policy — IAM propagation is near-instant but not always. Retry your Lambda.

2. Resource-Based Policy Blocks the Call

Even if your execution role is fine, the target resource (like an S3 bucket or SQS queue) might have its own policy that denies the request. AWS calls these resource-based policies. They override IAM roles.

Common trigger: You're trying to write to an S3 bucket that has a Deny statement for your Lambda's account. Or you're using a KMS key to encrypt data and the key's policy doesn't include your Lambda role.

I've seen this most often with cross-account setups. Lambda in Account A tries to write to S3 in Account B — the bucket policy in Account B has to explicitly allow the Lambda role from Account A. Without that, you get AccessDeniedException.

Fix it:

  1. Check the target resource's policy. For S3, it's the bucket policy. For SQS, it's the queue policy. For KMS, it's the key policy.
  2. Add a statement that allows the Lambda execution role's ARN to perform the needed actions.

Example bucket policy for cross-account S3 write:

{
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::123456789012:role/lambda-execution-role"
  },
  "Action": "s3:PutObject",
  "Resource": "arn:aws:s3:::my-bucket/*"
}

If you're using a customer-managed KMS key, add the Lambda role to the key policy under kms:Decrypt and kms:GenerateDataKey. Without those, Lambda can't read encrypted data.

3. VPC Configuration Blocks Outbound Access

This one's sneaky. You attach a VPC to your Lambda for security — good instinct — but then it can't reach AWS services like S3 or DynamoDB unless you give it a route. The result? A permission error that looks like IAM but is actually networking.

The classic sign: Your Lambda works fine without a VPC, but fails with AccessDeniedException once you assign it to a VPC. The function tries to call an AWS API, the request times out, and the SDK throws a generic permission denied.

I spent two hours on this once with a customer. They had the IAM role perfect but Lambda kept failing. Turns out the VPC had no NAT gateway and the subnets were private. Lambda couldn't reach the S3 endpoint.

Fix it:

  1. Set up a VPC endpoint for the service you're calling. For S3, create a gateway endpoint. For DynamoDB, create a gateway endpoint. For other services (SQS, SNS, KMS), use an interface endpoint.
  2. Or put Lambda in a public subnet with a NAT gateway — but that costs money and is less secure.
  3. Don't forget the security group: allow outbound HTTPS (port 443) to your VPC endpoint or to 0.0.0.0/0 if you're using a NAT.

Quick test: Remove the VPC from the Lambda function temporarily. If it works, it's networking. Add the VPC back and configure endpoints.

Quick-Reference Summary Table

Cause What to Check Fix
Execution role missing permissions IAM role attached to Lambda Attach policy for target service (e.g., S3, DynamoDB)
Resource-based policy denies access Bucket policy, queue policy, KMS key policy Add allow statement for Lambda role ARN
VPC blocks outbound traffic Lambda in VPC with no endpoint or NAT Add VPC endpoint or use public subnet with NAT

That's the short list. I've fixed hundreds of these across thousands of Lambda functions. Start with the role, then the resource policy, then the network. You'll nail it in under 10 minutes.

Was this solution helpful?