Debug a Lambda function that fails, times out or is throttled
A ranked checklist for a Lambda function that errors, times out, never runs or is throttled — read the error, read the logs, then check timeout, VPC route, permissions on both sides, state, concurrency and recursion, with the CLI command for each check.
markdownguidev4ZV3P-JR3Cstage: operatetrust: officialservice: lambdainterface: cliLambda not workingTask timed out afterLambda timeout VPCLambda throttledTooManyRequestsExceptionRate ExceededFunctionErrorCloudWatch Logs LambdaRuntime.ImportModuleErrorRuntime.NodejsExitResourceConflictException Pendingrecursive loopreserved concurrency 0
Get the actual error first. Invoke synchronously with --log-type Tail, or read the function's log group, and look the message up in reference/lambda/errors.md. Most failures are one of these: the 3-second default timeout, a VPC function with no route out, a missing permission on the execution role, or a missing permission on the function's own policy.
Step 0: reproduce and read
aws lambda invoke --function-name <fn> --cli-binary-format raw-in-base64-out \
--payload file://event.json --log-type Tail out.json
cat out.json # the function's return value, or {"errorType","errorMessage","trace"}
aws logs tail /aws/lambda/<fn> --since 30m --follow
# or search a wider window with Logs Insights: reference/cloudwatch/logs-insights-queries.md
The response's StatusCode is 200 even when the code threw. A function error shows as FunctionError in the response and an error object in out.json. A service error (throttle, missing permission, bad payload size) fails the CLI call itself with an exception name and a 4xx/5xx status. Those are different problems.
If the log group does not exist, the function has never run, or its role cannot write logs (missing AWSLambdaBasicExecutionRole).
Ranked checks
1. Timeout: Task timed out after N.NN seconds
- Timeout too short. The default is 3 seconds. Raise it with
aws lambda update-function-configuration --function-name <fn> --timeout 30(the maximum is 900). - The function waits on a network call that never answers. If the function is attached to a VPC, it has no internet access and no public IP, even in a public subnet. Calls to AWS APIs or the internet hang until the timeout. Fix: private subnets with a route to a NAT gateway, or VPC endpoints for the AWS services it calls (
patterns/lambda-in-vpc.md). Check:aws lambda get-function-configuration --function-name <fn> --query VpcConfig. - Slow downstream or cold start work. Log timestamps around each call. Set the SDK client's own timeouts below the function timeout so you get an error instead of a silent timeout.
2. Permission denied inside the function
AccessDenied or … is not authorized to perform: <action> from an SDK call means the execution role lacks the action. Add it to the role, not to your user. Find the role with aws lambda get-function-configuration --function-name <fn> --query Role. For S3 objects encrypted with KMS, also kms:Decrypt. To diagnose further: guides/iam/fix-access-denied.md.
3. Another service cannot invoke it
… is not authorized to perform: lambda:InvokeFunction on resource: … means the function's resource-based policy does not allow the caller. That applies to S3, EventBridge, SNS, API Gateway, or another account. Inspect it with aws lambda get-policy --function-name <fn>. Fix with add-permission or a full policy (reference/lambda/permissions.md). For a caller in the same account, an identity policy allowing lambda:InvokeFunction is enough.
4. Code or packaging
| Symptom | Likely cause |
|---|---|
Runtime.ImportModuleError / Cannot find module | Handler setting does not match the bundled file (index.handler → index.mjs or index.js at the zip root), or a dependency was not bundled. UNVERIFIED exact message text. |
Runtime.HandlerNotFound | The file exists but does not export that name. UNVERIFIED exact message text. |
Runtime.NodejsExit | The code called process.exit() or the event loop crashed. Return from the handler instead. |
Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap] | A custom runtime with no executable bootstrap in the package |
Runtime exited with error: signal: killed | Memory exhausted. Raise --memory-size. UNVERIFIED exact message text. |
5. State and in-flight updates
ResourceConflictException: … The function is currently in the following state: Pending means a create or update is still in progress. Use aws lambda wait function-updated-v2 --function-name <fn> before the next call. A function stuck Inactive or Failed reports why in StateReasonCode: aws lambda get-function-configuration --function-name <fn> --query '[State,StateReason,StateReasonCode,LastUpdateStatus]'. VPC (ENI or subnet) and KMS problems show here.
6. Throttling: TooManyRequestsException (429)
The account's concurrency is a per-Region quota shared by all functions. A function with reserved concurrency cannot exceed it, and reserved concurrency of 0 stops all invocations, sometimes set deliberately to break a loop. Check with aws lambda get-function-concurrency --function-name <fn> and aws lambda get-account-settings. Each function can also only add 1,000 execution environments every 10 seconds, so a sudden burst throttles even below the quota. Asynchronous sources (S3, SNS, EventBridge) retry throttled events. Synchronous callers must retry with backoff.
7. Runs repeatedly or never stops
- Asynchronous retries. Failed async invocations are retried up to two more times. Make the handler idempotent, and configure a failure destination or dead-letter queue to catch what still fails.
- Recursive loop. For example, a function that writes to the bucket or queue that triggers it. Lambda detects some loops and stops them (
RecursiveInvocationException). To stop one immediately:aws lambda put-function-concurrency --function-name <fn> --reserved-concurrent-executions 0. Then fix the trigger.
8. Payload too big
RequestTooLargeException (413) means the request exceeds the payload limit: 6 MB synchronous, 1 MB asynchronous. A response over 6 MB fails the synchronous invocation. Pass large data through S3 and send a reference.
Environment variables encrypted with a disabled key
KMSDisabledException: Lambda was unable to decrypt the environment variables because the KMS key used is disabled means the customer managed key on the function's environment is disabled. Re-enable the key, or update the function to use another key. The execution role needs kms:Decrypt on the key.
Still stuck
Compare against a minimal handler that only returns { ok: true }, with the same role, VPC and memory. If that fails too, the problem is configuration, not code.
Related: the invoke call and its retries (reference/lambda/invoke.md); runtime deprecation dates and fixed limits (reference/lambda/runtimes-and-limits.md); building and deploying TypeScript (guides/lambda/deploy-function.md).