Fluxtail
Troubleshooting

AWS Lambda Logs Not Showing: Destinations, Filters and Delivery

AWS Lambda logs not showing? Check the invoked version, custom log group, permissions, JSON log levels and delivery limits before changing configuration.

By Fluxtail Engineering

AWS Lambda runs application code without requiring you to manage an application server. Its runtime generates invocation records and relays output from your code to logging destinations such as Amazon CloudWatch Logs. These are different kinds of records: seeing a runtime report does not establish that every application message was emitted or delivered. AWS explains the Node.js logging path.

When AWS Lambda logs are not showing, first distinguish missing application output from a completely empty log destination. A function can write to a custom CloudWatch log group, and JSON logging can suppress messages below the configured application threshold. System records have a separate threshold. An invocation can therefore have visible runtime records while its console.log messages are intentionally excluded. AWS documents the separate filters.

The checks below focus on ordinary Lambda functions using CloudWatch Logs, with managed Node.js console logging as the example. Custom runtimes and Lambda Managed Instances need additional checks. Configuration and retained records can explain some missing output; an empty search alone cannot establish where a particular event disappeared.

How to find missing Lambda logs

Start with a known invocation: its approximate time, function, version and request ID if available. These checks help distinguish a search mistake, intentional filtering and a delivery problem. They do not prove that every message reached CloudWatch.

Confirm the invocation and destination

Check the AWS account and Region in both the caller and the CloudWatch console. Then confirm the exact function version the caller invoked. Editing $LATEST does not change an already published version used by a caller.

Use AWS CLI v2 to inspect a known version. Replace the sample function, Region and version with your own values:

aws lambda get-function-configuration \
  --function-name checkout-worker \
  --qualifier 12 \
  --region us-east-1 \
  --query '{Runtime:Runtime,Version:Version,Role:Role,LoggingConfig:LoggingConfig}' \
  --output json \
  --no-cli-pager

This is a read-only request. The projection displays the runtime, version, execution role and logging configuration without printing environment variables. The command returns version-specific settings; it does not establish which version a past invocation actually ran. AWS CLI command reference.

If the caller uses an alias, check its target version and any weighted routing. Inspect each version that could receive the request. Current alias settings alone may not describe an invocation made before a routing change.

Read LoggingConfig before choosing a log group. The default is /aws/lambda/<function name>, but Lambda also supports custom groups and groups shared by several functions. Custom-group stream names include the function name and version. Searching only the default group can hide existing records. AWS log-group documentation.

In the configured group, select a time window around the invocation. Remove restrictive message and severity filters, then search across streams for the request ID. Check whether older records have expired under the group's retention policy. A quiet stream is not necessarily the stream that handled your request.

Check permissions and both logging thresholds

The execution role belongs to the function; your own permission to read CloudWatch does not give the function permission to write there. Check that the role can create the required group and streams and put log events into the intended destination. AWSLambdaBasicExecutionRole is AWS's standard managed policy for basic logging.

Changing a log group through the CLI does not automatically add logs:PutLogEvents. Check the role when moving to a custom group rather than assuming the destination change grants access. AWS execution-role guidance.

Next inspect LogFormat, ApplicationLogLevel and SystemLogLevel. Lambda's log-level filtering requires JSON format. For supported Node.js console logging, console.log and console.info produce INFO records, while console.error produces ERROR records. An application threshold of WARN suppresses INFO messages but permits ERROR messages. System start and report records map to INFO and can also disappear when the system threshold is WARN. AWS filtering rules.

Check application logger settings too. If a library discards a message before writing it, changing Lambda's threshold cannot bring it back. If only one branch's output is missing, confirm that the deployed code reached that branch.

Compare two harmless markers

For a disposable test function using a supported managed Node.js runtime, save this as index.mjs and use the handler index.handler:

export const handler = async (_event, context) => {
  const marker = `lambda-log-check:${context.awsRequestId}`;
  console.info(`${marker} info-marker`);
  console.error(`${marker} error-marker`);
  return { requestId: context.awsRequestId };
};

The ERROR message is a diagnostic marker; the handler does not throw an error. It logs no event payload or credentials. Node.js console output becomes structured records when Lambda's log format is JSON. AWS Node.js logging documentation.

The table shows expected filtering behavior, assuming both statements execute and delivery succeeds. These are illustrative expectations, not captured test results.

JSON configuration INFO marker ERROR marker Destination to inspect
Application INFO, default group Eligible for delivery Eligible for delivery /aws/lambda/<function name>
Application ERROR, default group Filtered out Eligible for delivery /aws/lambda/<function name>
Application ERROR, custom group Filtered out Eligible for delivery Configured custom group

Keep the system threshold unchanged while comparing application thresholds. If you repeat the comparison with a custom group, record that group's name and permissions. Use each invocation's returned request ID to distinguish runs.

A synthetic ERROR record for this fixture could look like this; timestamps and IDs vary:

{
  "timestamp": "2026-11-08T18:00:00.000Z",
  "level": "ERROR",
  "message": "lambda-log-check:demo-request-42 error-marker",
  "requestId": "demo-request-42"
}

Finding the ERROR marker while INFO is filtered matches the configuration. Finding neither marker still requires destination, execution and delivery checks. Running the handler locally cannot verify Lambda's filtering or CloudWatch delivery.

Separate delay from possible delivery loss

AWS says logs can take 5–10 minutes to appear. Recheck the same invocation window before generating more test traffic. If records remain incomplete, inspect CloudWatch Logs quota utilization and the function's output rate.

AWS documents possible loss from CloudWatch throttling and excessive per-stream output. With JSON logging, Lambda tries to report dropped output through a logsDropped event, but that notification can also fail to arrive. Its absence does not prove complete delivery. AWS missing-log troubleshooting.

Avoid dumping whole requests to investigate volume problems. Use small markers and allowlisted context. If messages come from asynchronous work, check whether the handler returns before that work finishes. Do not replay production operations merely to produce logs.

After changing execution-role permissions, follow AWS's guidance to make a controlled code or configuration update so running environments with old credentials are replaced. This changes the running function and belongs in your normal deployment process. AWS execution troubleshooting.

Record the result precisely: which invocation you checked, its version and group, the thresholds, and which records you found. Keep an unexplained absence separate from a confirmed filtering rule.

Verify a captured event in Fluxtail

Once an application record is present in CloudWatch, you can separately check onward ingestion into Fluxtail. This sample check cannot recover output Lambda suppressed or establish why an event is absent from CloudWatch.

For a sanitized record with a string message, explicitly map timestamp to timestamp, level to severity, and message to message. Supply service_name yourself. Do not assume that sending the original Lambda object will normalize every field. Fluxtail payload reference.

For the synthetic row above, the mapped payload is:

{
  "timestamp": "2026-11-08T18:00:00.000Z",
  "severity": "ERROR",
  "service_name": "checkout-worker",
  "message": "lambda-log-check:demo-request-42 error-marker"
}

With your own sanitized captured row, follow the existing HTTP JSON ingestion example. It shows how to use the receiver's exact URL and Bearer token without placing the token directly in curl arguments.

HTTP acceptance and finding the stored row are separate checks. In the target stream's Live Tail, select the sample's original event-time window and search for its unique marker. A newly submitted historical event may require that older window rather than appearing as a fresh event. Fluxtail Live Tail documentation.

Finding the row establishes that this sample is stored and readable. It does not verify continuous CloudWatch forwarding. If the sample is absent, use log diagnostics to investigate the receiver and collection step separately from the original Lambda problem.