Skip to content

Bug: injectLambdaContext does not respect resetKeys when an error occurs #4121

Closed
@ajpower

Description

@ajpower

Expected Behavior

All keys appended by calling logger.appendKeys are cleared before the next invocation.

Current Behavior

If the Lambda function throws an error, then any keys appended will be present in the subsequent execution. At a minimum, they are present in the Lambda invocation event log if logEvents is enabled.

Code snippet

Here's a unit test that reproduces the issue. It uses sinon and chai but should be easily ported to other testing libraries. Imports are excluded for readability.

describe('injectLambdaContext', () => {
    const logger = new Logger({ serviceName: 'example' });
    let loggerStub: sinon.SinonStub;
    let capturedLoggerStates: unknown[] = [];

    beforeEach(() => {
        loggerStub = sinon.stub(logger, 'info').callThrough();
        loggerStub.withArgs('Lambda invocation event').callsFake(() => {
            // Capture logger's internal state when middleware logs invocation
            // @ts-ignore - accessing private field to capture logged attributes
            capturedLoggerStates.push({ ...(logger as any).temporaryLogAttributes });
        });
    });

    afterEach(() => {
        loggerStub.restore();
        capturedLoggerStates = [];
    });

    it('should clear log keys between invocations when an exception is thrown', async () => {
        const handlerFunction = async (): Promise<never> => {
            logger.appendKeys({ testKey: 'testValue' });
            throw new Error('oh no');
        };
        const handler = middy(handlerFunction).use(
            injectLambdaContext(logger, { logEvent: true, resetKeys: true }),
        );

        await expect(handler({}, lambdaContext)).to.be.rejected;
        await expect(handler({}, lambdaContext)).to.be.rejected;

        expect(capturedLoggerStates).to.have.length(
            2,
            'Expected two invocations to have been logged',
        );
        expect(capturedLoggerStates[1]).to.not.have.property('testKey'); // this assertion fails
    });
});

Steps to Reproduce

In addition to running the unit test, deploy a Lambda function that

  1. Appends keys to the logger
  2. Throws an exception

You'll see in the second Lambda invocation that the log line Lambda invocation event has those keys set.

Possible Solution

The issue is that we don't call resetKeys in the middleware's onError. We should either reset keys in the error handler, or move the logic to the before handler.

Powertools for AWS Lambda (TypeScript) version

latest

AWS Lambda function runtime

20.x

Packaging format used

npm

Execution logs

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcompletedThis item is complete and has been merged/shippedloggerThis item relates to the Logger Utility

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions