What's Actually Happening
AWS Lambda function cannot be invoked or fails during execution. API Gateway or other triggers receive errors when calling Lambda.
The Error You'll See
```bash $ aws lambda invoke --function-name my-function response.json
An error occurred (AccessDeniedException) when calling the Invoke operation ```
Internal error:
{
"errorMessage": "Internal server error",
"errorType": "InternalServerError"
}Function error:
{
"StatusCode": 200,
"FunctionError": "Unhandled",
"Payload": "{\"errorMessage\": \"ReferenceError: x is not defined\"}"
}Timeout error:
Task timed out after 30.00 secondsWhy This Happens
- 1.Permission denied - IAM role doesn't have invoke permission
- 2.Function not found - Function doesn't exist or wrong region
- 3.Runtime error - Code error in function execution
- 4.Timeout - Function execution exceeds timeout limit
- 5.Memory limit - Function exceeds memory limit
- 6.Throttling - Concurrent execution limit reached
Step 1: Check Function Exists
```bash # List Lambda functions: aws lambda list-functions
# Check specific function: aws lambda get-function --function-name my-function
# Check function in correct region: aws lambda get-function --function-name my-function --region us-east-1
# Check function ARN: aws lambda get-function --function-name my-function --query 'Configuration.FunctionArn'
# Check function state: aws lambda get-function --function-name my-function --query 'Configuration.State' # States: Active, Pending, Inactive, Failed
# Check function configuration: aws lambda get-function-configuration --function-name my-function
# Get function code location: aws lambda get-function --function-name my-function --query 'Code.Location' ```
Step 2: Check IAM Permissions
```bash # Check function execution role: aws lambda get-function-configuration --function-name my-function --query 'Configuration.Role'
# Check role has invoke permission: # For API Gateway to invoke Lambda, need: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "apigateway.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:region:account:function:function-name" } ] }
# Check role policies: aws iam list-role-policies --role-name lambda-role aws iam list-attached-role-policies --role-name lambda-role
# Add invoke permission: aws lambda add-permission \ --function-name my-function \ --statement-id apigateway-invoke \ --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com
# For cross-account invocation: aws lambda add-permission \ --function-name my-function \ --statement-id cross-account \ --action lambda:InvokeFunction \ --principal arn:aws:iam::ACCOUNT-ID:root
# Check policy: aws lambda get-policy --function-name my-function ```
Step 3: Check Function Logs
```bash # Check CloudWatch Logs: aws logs describe-log-streams \ --log-group-name /aws/lambda/my-function
# Get recent logs: aws logs get-log-events \ --log-group-name /aws/lambda/my-function \ --log-stream-name STREAM_NAME
# Use CloudWatch Logs Insights: # Query for errors: fields @timestamp, @message filter @message like /Error/ sort @timestamp desc limit 20
# In AWS Console: # CloudWatch -> Logs -> Log groups -> /aws/lambda/my-function
# Check for runtime errors: # - Python: Traceback # - Node.js: Error: ... # - Java: Exception in thread
# Use AWS CLI with tail: aws logs tail /aws/lambda/my-function --follow ```
Step 4: Check Function Configuration
```bash # Check timeout setting: aws lambda get-function-configuration \ --function-name my-function \ --query 'Configuration.Timeout'
# Default timeout: 3 seconds # Max: 900 seconds (15 minutes)
# Increase timeout: aws lambda update-function-configuration \ --function-name my-function \ --timeout 60
# Check memory: aws lambda get-function-configuration \ --function-name my-function \ --query 'Configuration.MemorySize'
# Default: 128 MB # Range: 128-10240 MB
# Increase memory: aws lambda update-function-configuration \ --function-name my-function \ --memory-size 512
# Check runtime: aws lambda get-function-configuration \ --function-name my-function \ --query 'Configuration.Runtime'
# Valid runtimes: python3.x, nodejs20.x, java21, etc.
# Check handler: aws lambda get-function-configuration \ --function-name my-function \ --query 'Configuration.Handler' # Format: filename.handler_function ```
Step 5: Fix Runtime Errors
```python # Python example - common errors:
# Error: ModuleNotFoundError # Fix: Check dependencies in requirements.txt or Lambda layer
# Error: TimeoutError # Fix: Increase timeout or optimize code
# Error: MemoryError # Fix: Increase memory size
# Check imports in handler: import json import boto3
def lambda_handler(event, context): try: # Your code return { 'statusCode': 200, 'body': json.dumps({'message': 'Success'}) } except Exception as e: print(f"Error: {str(e)}") return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}) }
# Node.js example: exports.handler = async (event) => { try { // Your code return { statusCode: 200, body: JSON.stringify({message: 'Success'}) }; } catch (error) { console.error('Error:', error); return { statusCode: 500, body: JSON.stringify({error: error.message}) }; } }; ```
Step 6: Check Concurrency Limits
```bash # Check reserved concurrency: aws lambda get-function-configuration \ --function-name my-function \ --query 'Configuration.ReservedConcurrentExecutions'
# Check account concurrency limit: aws lambda get-account-settings \ --query 'AccountLimit.ConcurrentExecutions'
# Default account limit: 1000 (varies by region)
# Set reserved concurrency: aws lambda put-function-concurrency \ --function-name my-function \ --reserved-concurrent-executions 100
# Remove reserved concurrency: aws lambda delete-function-concurrency \ --function-name my-function
# Check provisioned concurrency: aws lambda get-provisioned-concurrency-config \ --function-name my-function \ --qualifier alias-name
# Check throttles: aws cloudwatch get-metric-statistics \ --namespace AWS/Lambda \ --metric-name Throttles \ --dimensions Name=FunctionName,Value=my-function \ --statistics Sum \ --period 60 \ --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \ --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) ```
Step 7: Check Event Source Mapping
```bash # List event source mappings: aws lambda list-event-source-mappings --function-name my-function
# Check specific mapping: aws lambda get-event-source-mapping --uuid UUID
# For DynamoDB Streams: aws lambda create-event-source-mapping \ --function-name my-function \ --batch-size 100 \ --maximum-batching-window-in-seconds 5 \ --starting-position LATEST \ --event-source-arn arn:aws:dynamodb:region:account:table/table-name/stream/label
# For Kinesis: aws lambda create-event-source-mapping \ --function-name my-function \ --event-source-arn arn:aws:kinesis:region:account:stream/stream-name \ --starting-position LATEST
# For SQS: aws lambda create-event-source-mapping \ --function-name my-function \ --event-source-arn arn:aws:sqs:region:account:queue-name \ --batch-size 10
# Check mapping state: aws lambda get-event-source-mapping --uuid UUID --query 'State' # States: Enabled, Disabled, Creating, Enabling, Disabling ```
Step 8: Test Function Invocation
```bash # Invoke function directly: aws lambda invoke \ --function-name my-function \ --payload '{"key": "value"}' \ response.json
# Check response: cat response.json
# Invoke with CLI: aws lambda invoke \ --function-name my-function \ --invocation-type Event \ --payload file://event.json \ response.json
# Invocation types: # RequestResponse (default) - synchronous, wait for response # Event - asynchronous, doesn't wait
# Invoke specific version/alias: aws lambda invoke \ --function-name my-function:prod \ response.json
# Test with AWS Console: # Lambda -> Functions -> my-function -> Test # Create test event and run
# Dry run (validate): aws lambda invoke \ --function-name my-function \ --invocation-type DryRun \ response.json ```
Step 9: Check Function Dependencies
```bash # For Python: # Check requirements.txt: cat requirements.txt
# Package dependencies: pip install -r requirements.txt -t ./package
# Create deployment package: cd package zip -r ../function.zip . cd .. zip function.zip lambda_function.py
# Update function code: aws lambda update-function-code \ --function-name my-function \ --zip-file fileb://function.zip
# For Node.js: # Check package.json: cat package.json
# Install dependencies: npm install
# Create deployment package: zip -r function.zip index.js node_modules/
# Use Lambda Layers for shared dependencies: aws lambda publish-layer-version \ --layer-name my-layer \ --description "Common dependencies" \ --zip-file fileb://layer.zip \ --compatible-runtimes python3.11
# Add layer to function: aws lambda update-function-configuration \ --function-name my-function \ --layers arn:aws:lambda:region:account:layer:my-layer:version ```
Step 10: AWS Lambda Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-lambda.sh #!/bin/bash
FUNCTION=$1 REGION=${2:-"us-east-1"}
if [ -z "$FUNCTION" ]; then echo "Usage: $0 function-name [region]" exit 1 fi
echo "=== Function Configuration ===" aws lambda get-function-configuration --function-name $FUNCTION --region $REGION --query '{Runtime:Runtime, Handler:Handler, Timeout:Timeout, MemorySize:MemorySize, State:State}'
echo "" echo "=== Function Role ===" aws lambda get-function-configuration --function-name $FUNCTION --region $REGION --query 'Configuration.Role'
echo "" echo "=== Function Policy ===" aws lambda get-policy --function-name $FUNCTION --region $REGION 2>/dev/null || echo "No policy attached"
echo "" echo "=== Recent Logs (last 5) ===" STREAM=$(aws logs describe-log-streams --log-group-name /aws/lambda/$FUNCTION --region $REGION --order-by LastEventTime --descending --max-items 1 --query 'logStreams[0].logStreamName' --output text) aws logs get-log-events --log-group-name /aws/lambda/$FUNCTION --log-stream-name "$STREAM" --region $REGION --limit 5 2>/dev/null || echo "No logs found"
echo "" echo "=== Concurrency ===" aws lambda get-function-configuration --function-name $FUNCTION --region $REGION --query 'Configuration.ReservedConcurrentExecutions' 2>/dev/null || echo "No reserved concurrency"
echo "" echo "=== Event Source Mappings ===" aws lambda list-event-source-mappings --function-name $FUNCTION --region $REGION --query 'EventSourceMappings[].{UUID:UUID,State:State,Source:EventSourceArn}'
echo "" echo "=== Test Invocation ===" aws lambda invoke --function-name $FUNCTION --region $REGION --payload '{}' /tmp/response.json --query 'StatusCode' --output text echo "Response:" cat /tmp/response.json EOF
chmod +x /usr/local/bin/check-lambda.sh
# Usage: /usr/local/bin/check-lambda.sh my-function us-east-1
# Quick test: alias lambda-test='aws lambda invoke --payload' ```
AWS Lambda Checklist
| Check | Command | Expected |
|---|---|---|
| Function exists | get-function | Active state |
| Permissions | get-policy | Invoke allowed |
| Configuration | get-function-configuration | Correct timeout/memory |
| Logs | CloudWatch Logs | No runtime errors |
| Dependencies | deployment package | All required packages |
| Concurrency | get-function-concurrency | Within limits |
Verify the Fix
```bash # After fixing Lambda invocation
# 1. Test invocation aws lambda invoke --function-name my-function response.json // StatusCode: 200
# 2. Check response cat response.json // Success response
# 3. Check logs aws logs tail /aws/lambda/my-function // No errors
# 4. Verify permissions aws lambda get-policy --function-name my-function // Policy exists with invoke permission
# 5. Test from trigger # API Gateway or event source // Function invoked successfully
# 6. Monitor metrics aws cloudwatch get-metric-statistics --namespace AWS/Lambda --metric-name Invocations // Invocations increasing ```
Related Issues
- [Fix AWS Lambda Function Timeout](/articles/fix-aws-lambda-function-timeout)
- [Fix AWS Lambda Permission Denied](/articles/fix-aws-lambda-permission-denied)
- [Fix AWS API Gateway Integration Failed](/articles/fix-aws-api-gateway-integration-failed)