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:

json
{
  "errorMessage": "Internal server error",
  "errorType": "InternalServerError"
}

Function error:

json
{
  "StatusCode": 200,
  "FunctionError": "Unhandled",
  "Payload": "{\"errorMessage\": \"ReferenceError: x is not defined\"}"
}

Timeout error:

bash
Task timed out after 30.00 seconds

Why This Happens

  1. 1.Permission denied - IAM role doesn't have invoke permission
  2. 2.Function not found - Function doesn't exist or wrong region
  3. 3.Runtime error - Code error in function execution
  4. 4.Timeout - Function execution exceeds timeout limit
  5. 5.Memory limit - Function exceeds memory limit
  6. 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

CheckCommandExpected
Function existsget-functionActive state
Permissionsget-policyInvoke allowed
Configurationget-function-configurationCorrect timeout/memory
LogsCloudWatch LogsNo runtime errors
Dependenciesdeployment packageAll required packages
Concurrencyget-function-concurrencyWithin 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 ```

  • [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)