AWS Lambda Error: AccessDeniedException

 

AWS Lambda Error: AccessDeniedException

Why Lambda requests are denied by AWS services — and how to diagnose missing permissions, policy misalignment, and IAM trust issues.





Problem

Your Lambda executes but fails the moment it tries to access another AWS service. CloudWatch logs show an AccessDeniedException from S3, DynamoDB, SQS, STS, KMS, or another AWS API. Lambda itself runs fine — but the downstream call is rejected by IAM.

{
  "errorMessage": "AccessDeniedException:
    User: arn:aws:sts::<acct>:assumed-role/my-role/my-function
    is not authorized to perform: dynamodb:PutItem
    on resource: arn:aws:dynamodb:us-east-1:<acct>:table/MyTable",
  "errorType": "AccessDeniedException"
}

Top three causes at a glance:
• Missing IAM permissions for the AWS API being called
• Incorrect resource ARN (wrong table, bucket, key prefix, queue, or region)
• Wrong execution role assigned — or no role changes deployed


Clarifying the Issue

AccessDeniedException means Lambda was authenticated but not authorized. Your function’s execution role is real, valid, and trusted — but the IAM policies attached to it do not allow the action or do not match the resource. Lambda takes no corrective action; AWS simply denies the request.

Key diagnostic insights:

  • The execution role exists, but its policy lacks the required Action or Resource
  • Most AccessDenied errors are caused by overly specific ARNs, not missing permissions
  • Changing IAM roles does not automatically redeploy Lambdas that were using old versions

Why It Matters

AccessDenied errors break pipelines instantly. Event-driven architectures (SQS, DynamoDB Streams, SNS) will retry and eventually dead-letter. API Gateway integrations will fail. Batch workloads will stall. All because one IAM policy is misaligned.

Business and operational impact:

  • Immediate service disruption when Lambda cannot read/write its target resources
  • Retried messages can cause backlog floods and DLQ failures
  • Misconfigured ARNs often slip through reviews and only appear in production

Key Terms

  • Execution role – The IAM role Lambda assumes when running your function
  • Resource ARN – The fully qualified identifier of the target (table, bucket, queue)
  • Action – The AWS API operation being attempted (e.g., s3:GetObject)
  • Trust policy – Defines who can assume the role (usually Lambda service)

Steps at a Glance

  1. Identify the denied action and resource from CloudWatch logs.
  2. Verify the Lambda execution role name and ARN.
  3. Inspect the IAM policy for missing actions or wildcards.
  4. Confirm the resource ARN matches the actual AWS resource.
  5. Validate region, account ID, and prefix patterns.
  6. Add the required permissions and redeploy if needed.
  7. Test the Lambda with a manual invocation.
  8. Review CloudTrail for any hidden Deny statements.

Detailed Steps

Step 1: Identify the denied action and resource from CloudWatch logs.

Start by extracting the exact error from the recent logs.

aws logs tail /aws/lambda/my-function --since 5m

Look for lines like:

AccessDeniedException: User is not authorized to perform: dynamodb:PutItem

This gives you two critical pieces of information: the action (dynamodb:PutItem) and the resource ARN.

Now confirm the actual role Lambda is using.


Step 2: Verify the Lambda execution role name and ARN.

Retrieve the function configuration to ensure you’re inspecting the correct role.

aws lambda get-function-configuration \
  --function-name my-function \
  --query 'Role'

If the role is not the one you expected (common in CDK/SAM deployments), you may be editing the wrong policy.

Next, inspect the IAM policy permissions.


Step 3: Inspect the IAM policy for missing actions or wildcards.

List all policies attached to the execution role.

aws iam list-attached-role-policies \
  --role-name my-role

Then view the actual policy document:

aws iam get-policy-version \
  --policy-arn arn:aws:iam::<acct>:policy/MyPolicy \
  --version-id v1

Look for missing actions or overly narrow resources. Often the fix is simply adding a single missing line.

After checking permissions, confirm the ARN being used.


Step 4: Confirm the resource ARN matches the actual AWS resource.

Most AccessDenied errors are caused by incorrect ARNs, not missing permissions.

Examples of common mismatches:

  • S3 bucket ARN vs object ARN
  • DynamoDB table ARN vs table/index ARN
  • SQS queue URL vs ARN
  • Wrong region embedded in the ARN
  • Wildcards not matching prefixes

List resources to confirm:

aws dynamodb list-tables
aws s3 ls
aws sqs list-queues

Now verify region and account alignment.


Step 5: Validate region, account ID, and prefix patterns.

A single mis-typed account ID or region makes AWS deny access immediately.

Check:

aws sts get-caller-identity

If the resource ARN uses a different region or account, update your IAM policy accordingly.

Next, update the policy and reapply changes.


Step 6: Add the required permissions and redeploy if needed.

Modify the execution role to include the needed permissions.

Example (DynamoDB):

aws iam put-role-policy \
  --role-name my-role \
  --policy-name dynamodb-access \
  --policy-document file://policy.json

Remember: if your Lambda was deployed with an old role version, redeploy it.

Now test again.


Step 7: Test the Lambda with a manual invocation.

Run a controlled test payload:

aws lambda invoke \
  --function-name my-function \
  --payload '{}' \
  out.json

If the previous AccessDenied error no longer appears in logs, the permission is correct.

Finally, check for any organization-level policy blocks.


Step 8: Review CloudTrail for hidden Deny statements.

Sometimes access is denied by:

  • Service Control Policies (SCPs)
  • Resource-based policies
  • KMS key policies (a frequent cause for S3, DynamoDB, and Lambda environment decryption)
  • S3 bucket policies
  • Explicit "Deny" statements

Search CloudTrail for Deny events:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AccessDenied

If a secondary Deny appears, adjust the resource policy — not the Lambda role.


Pro Tips

Use IAM Policy Simulator

Test the exact action/ARN pair to validate effective permissions.

Prefer least-privilege with wildcards

For example: arn:aws:s3:::mybucket/* instead of dozens of object ARNs.

Redeploy when IAM roles change

Lambda may continue running with cached permissions unless redeployed.


Conclusion

AccessDeniedException means Lambda is authenticated but not authorized to perform the requested AWS operation. By identifying the denied action, verifying the execution role, correcting ARNs, and adjusting IAM policies, you can restore functionality and prevent cascading operational failures.


Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.

Comments

Popular posts from this blog

The New ChatGPT Reason Feature: What It Is and Why You Should Use It

Insight: The Great Minimal OS Showdown—DietPi vs Raspberry Pi OS Lite

Raspberry Pi Connect vs. RealVNC: A Comprehensive Comparison