Photo by Jordan Harrison on Unsplash
To invoke Lambda with AWS SDK v3 in TypeScript, create a LambdaClient and send an InvokeCommand with FunctionName, an InvocationType (RequestResponse to wait for the result, Event to fire and forget) and a Payload encoded as a Uint8Array. Decode the response Payload with TextDecoder, and check FunctionError before trusting it.
This example is for developers calling one Lambda function from another service, a script or a test harness. Most bugs here come from two v3 details: the payload is bytes, not a string, and a function that throws still returns HTTP 200. You’ll get a TypeScript helper that handles both, the least-privilege IAM policy, sample output for synchronous and asynchronous calls, and fixes for the common errors.
It’s one of our runnable AWS practical examples with SDK v3. To check how often your functions are called once they’re wired up, see the companion example to get the Lambda invocation count for the last 24 hours.
Synchronous or asynchronous: which InvocationType?
InvocationType |
What happens | Status code | Payload returned |
|---|---|---|---|
RequestResponse (default) |
Waits for the function to finish | 200 | Yes, plus FunctionError and optional log tail |
Event |
Queues the event and returns immediately; Lambda retries on function errors | 202 | No |
DryRun |
Checks that the caller is allowed to invoke, without running | 204 | No |
Use RequestResponse when the caller needs the result, such as an API calling a pricing function. Use Event for work that can happen later, such as sending an email. When several functions must run in order with retries, a state machine beats chained invokes; the guide to start a Step Functions execution from TypeScript with SDK v3 covers that call. The guide to send email with Amazon SES and AWS SDK v3 in TypeScript covers that part of such a function. Field-level details, including every response header, are in the Lambda Invoke API reference. When a function should run on a timetable rather than when your code calls it, create an EventBridge Scheduler schedule with AWS SDK v3 that invokes it.
Prerequisites
- Node.js 18 or later, npm and
tsx. @aws-sdk/client-lambda.- A deployed function and an AWS profile or role allowed to invoke it.
Which IAM permission does invoking need?
Just lambda:InvokeFunction, scoped to the function. The second ARN, with :*, covers invoking a specific version or alias such as orders-api:prod. Replace the region, account ID and function name:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeOneFunction",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": [
"arn:aws:lambda:us-east-1:123456789012:function:orders-api",
"arn:aws:lambda:us-east-1:123456789012:function:orders-api:*"
]
}
]
}
Invoking a function in another account also requires a resource-based policy on that function that allows your role. Function URLs bypass InvokeCommand and rely on that policy too; the script to find public Lambda function URLs with AuthType NONE checks which ones anyone can call. For generating a first draft from your own calling code, try the IAM policy generator for TypeScript AWS SDK code, then review the generated IAM policy for least privilege before you attach it.
The full script: invoke Lambda with AWS SDK v3 in TypeScript
// invoke-lambda.ts
// Invokes a Lambda function synchronously (RequestResponse) or asynchronously (Event)
// and decodes the response payload, function error and log tail.
import { LambdaClient, InvokeCommand, type InvocationType } from "@aws-sdk/client-lambda";
const region = process.env.AWS_REGION ?? "us-east-1";
// maxAttempts: 1 stops the SDK from retrying (and re-running) a function that isn't idempotent.
const lambda = new LambdaClient({ region, maxAttempts: 1 });
export async function invoke<T = unknown>(
functionName: string,
payload: unknown,
invocationType: InvocationType = "RequestResponse",
): Promise<T | undefined> {
const res = await lambda.send(
new InvokeCommand({
FunctionName: functionName, // name, name:alias, or full ARN
InvocationType: invocationType,
Payload: new TextEncoder().encode(JSON.stringify(payload)),
LogType: invocationType === "RequestResponse" ? "Tail" : "None",
}),
);
console.log(`StatusCode: ${res.StatusCode} ExecutedVersion: ${res.ExecutedVersion ?? "-"}`);
if (res.LogResult) {
// The last 4 KB of the execution log, base64-encoded
console.log("--- log tail ---");
console.log(Buffer.from(res.LogResult, "base64").toString("utf8").trim());
console.log("----------------");
}
if (invocationType !== "RequestResponse") return undefined; // Event returns 202 and no payload
const text = res.Payload ? new TextDecoder().decode(res.Payload) : "";
if (res.FunctionError) {
// The API call succeeded (StatusCode 200) but the handler threw or timed out.
throw new Error(`Function error (${res.FunctionError}): ${text}`);
}
return text ? (JSON.parse(text) as T) : undefined;
}
async function main(): Promise<void> {
const [functionName, json = "{}", mode = "sync"] = process.argv.slice(2);
if (!functionName) {
console.error("Usage: npx tsx invoke-lambda.ts <function> [json-payload] [sync|async]");
process.exit(1);
}
const type: InvocationType = mode === "async" ? "Event" : "RequestResponse";
const result = await invoke(functionName, JSON.parse(json), type);
if (result !== undefined) console.log("Result:", JSON.stringify(result, null, 2));
}
main().catch((err) => {
console.error(err instanceof Error ? err.message : err);
process.exit(1);
});
How do you decode the Lambda invoke response payload in TypeScript?
In v3, the request Payload is a Uint8Array and the response Payload is a Uint8Array subclass. new TextDecoder().decode(res.Payload) turns it into the JSON string your handler returned, and JSON.parse does the rest. Calling JSON.parse(res.Payload) directly, a common habit from SDK v2 where the payload was already a string, fails at compile time in TypeScript and at runtime in JavaScript.
Why check FunctionError?
If your handler throws or times out, the Invoke call still succeeds with StatusCode: 200. The failure shows up only as FunctionError: "Unhandled", and the payload holds an error object with errorType and errorMessage. The helper turns that into a thrown Error, so callers can’t accidentally treat an error object as a result.
How do you run it?
npm install @aws-sdk/client-lambda
npm install --save-dev tsx typescript @types/node
# Synchronous: wait for the result
AWS_PROFILE=dev AWS_REGION=us-east-1 npx tsx invoke-lambda.ts orders-api '{"orderId":"A-1001"}'
# Asynchronous: queue the event and return
AWS_PROFILE=dev AWS_REGION=us-east-1 npx tsx invoke-lambda.ts send-receipt '{"orderId":"A-1001"}' async
Sample output
StatusCode: 200 ExecutedVersion: $LATEST
--- log tail ---
START RequestId: 5f1c9a2e-8d7b-4c1a-9e3f-2b6d0a7c4e11 Version: $LATEST
END RequestId: 5f1c9a2e-8d7b-4c1a-9e3f-2b6d0a7c4e11
REPORT RequestId: 5f1c9a2e-8d7b-4c1a-9e3f-2b6d0a7c4e11 Duration: 41.87 ms Billed Duration: 42 ms Memory Size: 256 MB Max Memory Used: 88 MB
----------------
Result: {
"orderId": "A-1001",
"status": "PAID",
"total": 42.5
}
StatusCode: 202 ExecutedVersion: -
The second line block is the asynchronous call: a 202 means Lambda accepted the event, not that the function succeeded. Check the function’s logs or a destination for the outcome.
Troubleshooting Lambda InvokeCommand errors
AccessDeniedException. The caller lackslambda:InvokeFunctionon that ARN. If you passname:alias, the policy needs the:*ARN too.ResourceNotFoundException. Wrong name, wrong region, or a version or alias that doesn’t exist. Lambda functions are regional, so checkAWS_REGION.Function error (Unhandled)withTask timed out. The function hit its configured timeout. Raise it or find the slow call; the guides to investigate Lambda errors and timeouts with CloudWatch and to ask AI about Lambda errors in your AWS account walk through both.RequestEntityTooLargeException. The payload is over the invocation limit (6 MB for synchronous calls, according to AWS’s Lambda quotas documentation). Pass an S3 key instead of the data.TooManyRequestsException. The function or account reached its concurrency limit. Retry with backoff, or raise reserved concurrency.- A side effect happened twice. The SDK retried after a network error. The script sets
maxAttempts: 1; for functions that must run once, also make the handler idempotent. The guide to configure retries and timeouts in AWS SDK for JavaScript v3 explains which errors the SDK retries.
When the cause isn’t in Lambda at all, the wider method to troubleshoot AWS infrastructure with an AI CLI follows the problem into other services.
Lambda client InvokeCommand in JavaScript: what changes from v2?
In SDK v2 you called lambda.invoke(params).promise() and got Payload back as a string. In v3 you send an InvokeCommand through a modular LambdaClient, the payload is bytes, and TypeScript types come built in. The same script works as plain JavaScript by removing the type annotations. To port a larger v2 codebase, the free converter for AWS SDK v2 to v3 JavaScript rewrites the calls; review its output before deploying. The step-by-step plan to migrate a Node.js app from AWS SDK v2 to v3 covers pagination, errors and tests. Because v3 clients are modular, a function that imports only LambdaClient can ship a much smaller package; the guide to reduce AWS SDK v3 bundle size and cold starts in Lambda shows how.
Ask ChatWithCloud instead
For read-only questions about your functions, ChatWithCloud is quicker than writing code: ask “What timeout, memory and runtime does orders-api have, and did it error today?” It writes AWS SDK for JavaScript v2 code, runs it on your machine with your AWS profile, and explains the result (the step-by-step ChatWithCloud workflow shows the loop). Be careful with requests like “invoke orders-api”: changes and invocations run without a confirmation step. Connect ChatWithCloud with a read-only AWS profile that lacks lambda:InvokeFunction when you only want answers, and see the ChatWithCloud security model and data flow for what leaves your machine.
Frequently asked questions
How do I invoke Lambda asynchronously with Node.js SDK v3?
Set InvocationType: "Event" on the InvokeCommand. The call returns StatusCode: 202 once Lambda has queued the event, with no payload. Lambda retries the function on errors, so configure a destination or dead-letter queue to catch failures. An SQS queue is a common choice; see how to send and receive SQS messages with AWS SDK v3 in TypeScript to process what lands there.
How do I invoke Lambda synchronously with AWS SDK v3?
Use InvocationType: "RequestResponse", which is also the default. The call waits until the handler returns and gives you the payload, FunctionError if it failed, and the log tail if you set LogType: "Tail".
How do I invoke a specific alias or version?
Append it to the name (orders-api:prod) or pass it as Qualifier. ExecutedVersion in the response tells you which version actually ran. Once old versions pile up, the example to delete old Lambda versions that no alias uses cleans them up.
Can I stream the response instead of waiting for the whole payload?
Yes, for functions built for response streaming, with InvokeWithResponseStreamCommand. Standard handlers use InvokeCommand as shown here.
Related guides
Ask your AWS account in plain English
Your first 15 runs are free, with no OpenAI key needed.
npx chatwithcloud