Skip to content

Using a config object to set timeout settings causes an error to be thrown when multiple calls are made. #7076

Open
@PhilTower

Description

@PhilTower

Checkboxes for prior research

Describe the bug

Configuring a client with a config object to control:

    requestHandler: {
      requestTimeout: 2000,
      connectionTimeout: 2000,
      httpAgent: {
        timeout: 2000,
      },
      httpsAgent: {
        timeout: 2000,
      },
    }

timeout will cause a lambda to terminate early without error. When the lambda executes again, it will execute the current and previous iteration and at some point will log an error.

ERROR Invocation has already been reported as done. Cannot call complete more than once per invocation.

I do not know if this is a bug in lambda, the smithy client or both. I did not test this other sdk clients.

This does not occur when using NodeHttpHandler to configure the timeout control

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@smithy/smithy-client@4.2.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

22

Reproduction Steps

import { KinesisClient, PutRecordsCommand } from "@aws-sdk/client-kinesis";
import { Agent } from "https";
import { NodeHttpHandler } from "@aws-sdk/node-http-handler";

const getBrokenClient = function () {
  return new KinesisClient({
    requestHandler: {
      requestTimeout: 2000,
      connectionTimeout: 2000,
      httpAgent: {
        timeout: 2000,
      },
      httpsAgent: {
        timeout: 2000,
      },
    },
  });
}
const getWorkingClient = function () {
  return new KinesisClient({
    requestHandler: new NodeHttpHandler({
      httpsAgent: new Agent({}),
      connectionTimeout: 2000,
      requestTimeout: 2000,
      socketTimeout: 2000,
    }),
  });

};

const client = getBrokenClient();

const encoder = new TextEncoder();

let awsRequestId = undefined;

const drinkOptions = [
  "coffee", "water", "tea", "soda", "mocha",
  "milk", "oj"
];

let counter = 0;
export const handler = async (event, ctx) => {
  const iteration = ++counter;
  console.log(`iteration:${iteration} INFO Execute lambda request ${ctx.awsRequestId} last request ${awsRequestId}`);
  awsRequestId = ctx.awsRequestId;


  const drinks = process.env.MULTI === "true" ? drinkOptions :drinkOptions[0];

  for (const drink of drinks) {
    const command = new PutRecordsCommand({
      StreamARN: process.env.STREAM_ARN,
      Records: [{
        Data: serialize(mapMessage(drink)),
        PartitionKey: `${new Date().getTime()}-${drink}`,
      }]
    });

    const result = await client.send(command);
    console.log(`iteration:${iteration} INFO Sent to ${drink} kinesis ${result.$metadata.httpStatusCode} ${result.$metadata.requestId}`);
  }

  console.log(`iteration:${iteration} INFO Finished executing lambda request`);

  return { statusCode: 200, body: "OK" };
};

const serialize = function (object) {
  return encoder.encode(JSON.stringify(object));
}
const mapMessage = function (sample) {
  return {
    time: new Date().toISOString(),
    value: sample.length,
    sample,
    id: `${new Date().toISOString()}-${sample}`
  }
}

Observed Behavior

The lambda will stop executing and exit. In the next iteration the following error will be thrown.

ERROR Invocation has already been reported as done. Cannot call complete more than once per invocation.

	START RequestId: LambdaRequest-1 Version: $LATEST
	2025-05-13T15:16:08.478Z LambdaRequest-1 INFO iteration :1 INFO Execute lambda request LambdaRequest-1 last request undefined
	2025-05-13T15:16:09.334Z LambdaRequest-1 INFO iteration :1 INFO Sent to coffee kinesis 200 
	2025-05-13T15:16:09.395Z LambdaRequest-1 INFO iteration :1 INFO Sent to water kinesis 200
	2025-05-13T15:16:09.514Z LambdaRequest-1 INFO iteration :1 INFO Sent to tea kinesis 200
	2025-05-13T15:16:09.553Z LambdaRequest-1 INFO iteration :1 INFO Sent to soda kinesis 200
	2025-05-13T15:16:09.716Z LambdaRequest-1 INFO iteration :1 INFO Sent to mocha kinesis 200	
	2025-05-13T15:16:09.753Z LambdaRequest-1 INFO iteration :1 INFO Sent to milk kinesis 200
	END RequestId: LambdaRequest-1
	REPORT RequestId: LambdaRequest-1 Duration: 1661.80 ms Billed Duration: 1662 ms Memory Size: 128 MB Max Memory Used: 101 MB
	START RequestId: LambdaRequest-2 Version: $LATEST	
	2025-05-13T15:16:12.315Z LambdaRequest-2 INFO iteration :2 INFO Execute lambda request LambdaRequest-2 last request LambdaRequest-1
	2025-05-13T15:16:12.396Z LambdaRequest-2 INFO iteration :2 INFO Sent to coffee kinesis 200
	2025-05-13T15:16:12.575Z LambdaRequest-2 INFO iteration :1 INFO Sent to oj kinesis 200
	2025-05-13T15:16:12.575Z LambdaRequest-2 INFO iteration :1 INFO Finished executing lambda request
	2025-05-13T15:16:12.575Z LambdaRequest-2 ERROR Invocation has already been reported as done. Cannot call complete more than once per invocation.
	2025-05-13T15:16:12.576Z LambdaRequest-2 INFO iteration :2 INFO Sent to water kinesis 200
	2025-05-13T15:16:12.694Z LambdaRequest-2 INFO iteration :2 INFO Sent to tea kinesis 200
	END RequestId: LambdaRequest-2
	REPORT RequestId: LambdaRequest-2 Duration: 523.15 ms Billed Duration: 524 ms Memory Size: 128 MB Max Memory Used: 102 MB Status: error Error Type: Runtime.ExitError

Expected Behavior

For the error not to occur and the lambda to complete its execution normally.

Possible Solution

No response

Additional Information/Context

No response

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.closing-soonThis issue will automatically close in 4 days unless further comments are made.p3This is a minor priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions