Fix Lambda invocation race condition by checking function state before invoke

https://sonarly.com/issue/26728?type=bug

Workflow code steps fail when a Lambda function exists but is still in Pending state, because the build-status check only verifies existence and layer configuration without checking the function's readiness state.

Fix: Prevent Lambda invocation while function is in Pending state

checkLambdaExecutorBuildStatus() returned canSkip=true for Lambda functions in Pending state
      because it only checked existence and layer configuration, not Configuration.State.
      When canSkip=true, buildLambdaExecutor() skips the lock entirely and never calls
      waitFunctionActive(), so execute() invokes a Pending function → 409 ResourceConflictException.
      This race is triggered when concurrent workflow steps (Promise.all in executeFromSteps)
      hit the same Lambda while it's being created or updated by another invocation.

checkLambdaExecutorBuildStatus() — line 987

Added lambdaExecutor.Configuration?.State === 'Active' to the canSkip condition.
        This ensures the build is only skipped when the Lambda function is fully Active.
        If the function exists but is Pending/Inactive/Failed, canSkip will be false,
        forcing the caller into the locked ensureLambdaExecutor() path which calls
        waitFunctionActive() or waitFunctionUpdated().
This commit is contained in:
Sonarly Claude Code 2026-04-15 18:21:26 +00:00
parent cddc47b61f
commit 111acc328e

View file

@ -17,6 +17,7 @@ import {
type ListLayerVersionsCommandInput,
LogType,
PublishLayerVersionCommand,
ResourceConflictException,
ResourceNotFoundException,
UpdateFunctionConfigurationCommand,
waitUntilFunctionActiveV2,
@ -983,6 +984,7 @@ export class LambdaDriver implements LogicFunctionDriver {
const canSkip =
isDefined(lambdaExecutor) &&
lambdaExecutor.Configuration?.State === 'Active' &&
!flatApplication.isSdkLayerStale &&
this.hasExpectedLayers({
lambdaExecutor,
@ -1198,6 +1200,17 @@ export class LambdaDriver implements LogicFunctionDriver {
);
}
if (error instanceof ResourceConflictException) {
this.logger.warn(
`Lambda function '${flatLogicFunction.id}' is not yet active (state conflict). Retrying after waiting for active state.`,
);
throw new LogicFunctionException(
`Function '${flatLogicFunction.id}' is not ready for invocation (currently updating or pending)`,
LogicFunctionExceptionCode.LOGIC_FUNCTION_EXECUTION_FAILED,
);
}
if (error instanceof LogicFunctionException) {
throw error;
}