Introduction

Lambda triggers from services like S3, SNS, DynamoDB, or API Gateway require explicit permissions. These are stored in Lambda's resource-based policy. When a trigger source tries to invoke Lambda without permission, the request is denied and the event is not processed.

Symptoms

S3 trigger error:

```bash $ aws s3api put-bucket-notification-configuration --bucket my-bucket ...

An error occurred (AccessDenied) when calling the PutBucketNotificationConfiguration operation: Access Denied ```

Lambda invocation denied:

```bash $ aws lambda invoke --function-name my-function ...

AccessDeniedException: User: arn:aws:iam::123456789:user/test is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:region:account:function:my-function ```

Event source mapping error:

```bash $ aws lambda create-event-source-mapping ...

ResourceConflictException: The resource you requested already exists. # Or: InvalidParameterValueException: Lambda function does not have permission to access the event source ```

CloudTrail shows denied invocations:

```bash $ aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=InvokeFunction

"errorCode": "AccessDenied" "errorMessage": "User is not authorized to perform: lambda:InvokeFunction" ```

Common Causes

  1. 1.Missing resource-based policy - No permission for trigger source
  2. 2.Wrong principal in policy - Policy allows wrong service/account
  3. 3.Event source not configured - Trigger created but mapping missing
  4. 4.IAM execution role insufficient - For event source access
  5. 5.Cross-account permission missing - Different account triggers
  6. 6.Policy statement removed - Deleted or updated incorrectly
  7. 7.Kinesis/DynamoDB stream permissions - Missing stream read access

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Check Lambda Resource-Based Policy

```bash # Get function policy aws lambda get-policy --function-name my-function

# Output shows statements allowing invoke: { "Policy": { "Statement": [ { "Effect": "Allow", "Principal": {"Service": "s3.amazonaws.com"}, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:...", "Condition": {"ArnLike": {"AWS:SourceArn": "arn:aws:s3:::my-bucket"}} } ] } } ```

If policy is empty or missing:

```bash # Add permission for S3 trigger aws lambda add-permission \ --function-name my-function \ --statement-id s3-trigger \ --action "lambda:InvokeFunction" \ --principal s3.amazonaws.com \ --source-arn arn:aws:s3:::my-bucket

# Add permission for SNS trigger aws lambda add-permission \ --function-name my-function \ --statement-id sns-trigger \ --action "lambda:InvokeFunction" \ --principal sns.amazonaws.com \ --source-arn arn:aws:sns:region:account:my-topic

# Add permission for API Gateway aws lambda add-permission \ --function-name my-function \ --statement-id apigateway-trigger \ --action "lambda:InvokeFunction" \ --principal apigateway.amazonaws.com \ --source-arn arn:aws:execute-api:region:account:api-id/*/POST/path ```

Step 2: Check Event Source Mapping

```bash # List existing mappings aws lambda list-event-source-mappings --function-name my-function

# Get specific mapping aws lambda get-event-source-mapping --uuid mapping-uuid

# For Kinesis/DynamoDB/SQS streams: # Check mapping status aws lambda get-event-source-mapping --uuid mapping-uuid \ --query '{State:State,LastProcessingResult:LastProcessingResult}' ```

Create missing mapping:

```bash # Kinesis stream aws lambda create-event-source-mapping \ --function-name my-function \ --event-source-arn arn:aws:kinesis:region:account:stream/my-stream \ --starting-position LATEST

# DynamoDB stream aws lambda create-event-source-mapping \ --function-name my-function \ --event-source-arn arn:aws:dynamodb:region:account:table/my-table/stream/2024-01-01 \ --starting-position LATEST

# SQS queue aws lambda create-event-source-mapping \ --function-name my-function \ --event-source-arn arn:aws:sqs:region:account:my-queue ```

Step 3: Verify IAM Execution Role

For stream-based triggers, execution role needs stream read access:

```bash # Get execution role aws lambda get-function-configuration --function-name my-function \ --query 'Role'

# Check role permissions aws iam get-role-policy --role-name lambda-exec-role --policy-name stream-access

# Required permissions for Kinesis/DynamoDB: { "Effect": "Allow", "Action": [ "kinesis:GetRecords", "kinesis:GetShardIterator", "kinesis:DescribeStream", "dynamodb:DescribeStream", "dynamodb:GetRecords", "dynamodb:GetShardIterator" ], "Resource": "*" } ```

Add missing permissions:

bash
aws iam put-role-policy \
  --role-name lambda-exec-role \
  --policy-name kinesis-access \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": [
        "kinesis:GetRecords",
        "kinesis:GetShardIterator",
        "kinesis:DescribeStream",
        "kinesis:ListStreams"
      ],
      "Resource": "*"
    }]
  }'

Step 4: Configure S3 Bucket Notification

```bash # Check bucket notification configuration aws s3api get-bucket-notification-configuration --bucket my-bucket

# Add Lambda notification aws s3api put-bucket-notification-configuration \ --bucket my-bucket \ --notification-configuration '{ "LambdaFunctionConfigurations": [{ "Id": "my-notification", "LambdaFunctionArn": "arn:aws:lambda:region:account:function:my-function", "Events": ["s3:ObjectCreated:*"], "Filter": {"Key": {"FilterRules": [{"Name": "prefix", "Value": "images/"}]}} }] }' ```

Step 5: Handle Cross-Account Triggers

For Lambda in Account A triggered by S3 in Account B:

Account A (Lambda):

bash
aws lambda add-permission \
  --function-name my-function \
  --statement-id cross-account-s3 \
  --action "lambda:InvokeFunction" \
  --principal s3.amazonaws.com \
  --source-arn arn:aws:s3:::bucket-in-account-b \
  --source-account account-b-id

Account B (S3):

bash
aws s3api put-bucket-notification-configuration \
  --bucket bucket-in-account-b \
  --notification-configuration '{
    "LambdaFunctionConfigurations": [{
      "Id": "cross-account-notification",
      "LambdaFunctionArn": "arn:aws:lambda:region:account-a:function:my-function",
      "Events": ["s3:ObjectCreated:*"]
    }]
  }'

Step 6: Check for Permission Conflicts

```bash # View all policy statements aws lambda get-policy --function-name my-function \ --query 'Policy.Statement[*].[Sid,Principal,Action,Condition]'

# Remove conflicting statement aws lambda remove-permission \ --function-name my-function \ --statement-id old-permission

# Add corrected permission aws lambda add-permission \ --function-name my-function \ --statement-id new-permission \ --action "lambda:InvokeFunction" \ --principal sns.amazonaws.com \ --source-arn arn:aws:sns:region:account:my-topic ```

Step 7: Verify API Gateway Integration

```bash # Check API Gateway integration aws apigateway get-integration \ --rest-api-id api-id \ --resource-id resource-id \ --http-method POST

# Integration should show: # "type": "AWS_PROXY", # "uri": "arn:aws:apigateway:region:lambda:path/2015-03-31/functions/arn:aws:lambda:region:account:function:my-function/invocations"

# Add permission if missing aws lambda add-permission \ --function-name my-function \ --statement-id apigateway-invoke \ --action "lambda:InvokeFunction" \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:region:account:api-id/*/*/path" ```

Step 8: Test Trigger Permissions

```bash # Test S3 trigger by uploading file aws s3 cp test.txt s3://my-bucket/test.txt

# Check Lambda logs aws logs filter-log-events \ --log-group-name /aws/lambda/my-function \ --start-time $(date -d '5 minutes ago' +%s)000

# Test SNS trigger aws sns publish \ --topic-arn arn:aws:sns:region:account:my-topic \ --message "test"

# Test direct invoke aws lambda invoke --function-name my-function output.json ```

Step 9: Debug Event Source Mapping Issues

```bash # Get mapping details aws lambda get-event-source-mapping --uuid mapping-uuid

# Common states: # - Creating: Setup in progress # - Enabled: Working # - Disabled: Paused # - Disabling: Being paused

# LastProcessingResult errors: # - "No records processed": Nothing in stream # - "Problem processing records": Check Lambda logs # - "AccessDenied": IAM role issue

# Enable disabled mapping aws lambda update-event-source-mapping \ --uuid mapping-uuid \ --enabled

# Disable failing mapping temporarily aws lambda update-event-source-mapping \ --uuid mapping-uuid \ --no-enabled ```

Step 10: Monitor Trigger Failures

```bash # CloudTrail for denied invocations aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=EventName,AttributeValue=InvokeFunction \ --start-time $(date -d '1 hour ago' +%s)000 \ --query 'Events[*].CloudTrailEvent'

# Dead-letter queue for failed events (if configured) aws sqs receive-message --queue-url https://sqs.region.amazonaws.com/account/dlq

# Lambda error metrics aws cloudwatch get-metric-statistics \ --namespace AWS/Lambda \ --metric-name Errors \ --dimensions Name=FunctionName,Value=my-function \ --statistics Sum \ --period 300 ```

Trigger Permission Reference

Trigger SourcePrincipalRequired Permission
S3s3.amazonaws.comlambda:InvokeFunction
SNSsns.amazonaws.comlambda:InvokeFunction
DynamoDB Streamdynamodb.amazonaws.comlambda:InvokeFunction + stream read
Kinesiskinesis.amazonaws.comlambda:InvokeFunction + stream read
SQSsqs.amazonaws.comlambda:InvokeFunction + sqs:ReceiveMessage
API Gatewayapigateway.amazonaws.comlambda:InvokeFunction
CloudWatch Eventsevents.amazonaws.comlambda:InvokeFunction
CloudWatch Logslogs.amazonaws.comlambda:InvokeFunction

Verification

```bash # Test the trigger aws s3 cp test.txt s3://my-bucket/test.txt

# Check Lambda received event aws logs filter-log-events \ --log-group-name /aws/lambda/my-function \ --filter-pattern "START RequestId" \ --start-time $(date -d '2 minutes ago' +%s)000

# Should show successful invocation ```

  • [Fix AWS Lambda Function Timeout](/articles/fix-aws-lambda-function-timeout)
  • [Fix AWS S3 Event Notification Not Working](/articles/fix-aws-s3-bucket-policy-denied)
  • [Fix AWS SNS Topic Subscription Failed](/articles/fix-aws-lambda-destination-not-delivered)
  • [AWS troubleshooting: Fix IAM Permission Denied - Complete Tro](fix-iam-permission-denied)
  • [AWS cloud troubleshooting: AWS ACM Certificate Pending Validation Because the](aws-acm-certificate-pending-validation-wrong-route53-zone)
  • [AWS cloud troubleshooting: AWS ALB Returns 502 Because the Target Closed the ](aws-alb-502-target-closed-connection-keepalive-timeout-mismatch)
  • [AWS cloud troubleshooting: Fix AWS ALB CreateListener TargetGroupNotFound Err](aws-alb-createlistener-targetgroupnotfound)
  • [AWS cloud troubleshooting: Fix Aws Alb Lambda 502 Bad Gateway Issue in AWS](aws-alb-lambda-502-bad-gateway)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix AWS Lambda Trigger Permission Denied", "description": "Troubleshoot Lambda trigger permission denied errors. Fix resource-based policies, IAM roles, and event source mappings.", "url": "https://www.fixwikihub.com/fix-aws-lambda-trigger-permission-denied", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-01T15:04:58.365Z", "dateModified": "2026-04-01T15:04:58.365Z" } </script>