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.Missing resource-based policy - No permission for trigger source
- 2.Wrong principal in policy - Policy allows wrong service/account
- 3.Event source not configured - Trigger created but mapping missing
- 4.IAM execution role insufficient - For event source access
- 5.Cross-account permission missing - Different account triggers
- 6.Policy statement removed - Deleted or updated incorrectly
- 7.Kinesis/DynamoDB stream permissions - Missing stream read access
Step-by-Step Fix
- 1.Check logs for specific error messages
- 2.Verify configuration settings
- 3.Test network connectivity
- 4.Review recent changes
- 5.Apply corrective action
- 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:
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):
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-idAccount B (S3):
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 Source | Principal | Required Permission |
|---|---|---|
| S3 | s3.amazonaws.com | lambda:InvokeFunction |
| SNS | sns.amazonaws.com | lambda:InvokeFunction |
| DynamoDB Stream | dynamodb.amazonaws.com | lambda:InvokeFunction + stream read |
| Kinesis | kinesis.amazonaws.com | lambda:InvokeFunction + stream read |
| SQS | sqs.amazonaws.com | lambda:InvokeFunction + sqs:ReceiveMessage |
| API Gateway | apigateway.amazonaws.com | lambda:InvokeFunction |
| CloudWatch Events | events.amazonaws.com | lambda:InvokeFunction |
| CloudWatch Logs | logs.amazonaws.com | lambda: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 ```
Related Issues
- [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)
Related Articles
- [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>