-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Describe the bug
I'm using @aws-cdk/toolkit-lib to deploy stacks programmatically.
As of recently, when bumping @aws-sdk/client-cloudformation to 3.938.0 these deploys started to fail with
{
"$metadata" : {
"httpStatusCode" : 400,
"requestId" : "aac64c94-6168-4c3c-a080-eecfca52b5dd",
"attempts" : 1,
"totalRetryDelay" : 0
},
"$fault" : "client",
"Type" : "Sender",
"Code" : "ValidationError",
"Error" : {
"Type" : "Sender",
"Code" : "ValidationError",
"Message" : "Stack with id e2e-deploy-bert-degeyter does not exist"
}
}
After some debugging, it appears that the Error object/structure has changed slightly, and this has a detrimental impact on stack-helpers.ts, more specifically these lines:
if (e.name === 'ValidationError' && formatErrorMessage(e) === `Stack with id ${stackName} does not exist`) {
return new CloudFormationStack(cfn, stackName, undefined);
}
It appears that formatErrorMessage is not able to deal with these new errors being thrown from the updated cloudformation sdk client. Hence, the original error being forwarded and cdk.deploy(...) failing.
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Version
No response
Expected Behavior
deploy(...) should not fail when a Stack does not yet exist
Current Behavior
deploy(...) fails with the following error whenever a stack with a certain ID does not yet exist:
{
"$metadata" : {
"httpStatusCode" : 400,
"requestId" : "aac64c94-6168-4c3c-a080-eecfca52b5dd",
"attempts" : 1,
"totalRetryDelay" : 0
},
"$fault" : "client",
"Type" : "Sender",
"Code" : "ValidationError",
"Error" : {
"Type" : "Sender",
"Code" : "ValidationError",
"Message" : "Stack with id e2e-deploy-bert-degeyter does not exist"
}
}
Reproduction Steps
Use @aws-cdk/toolkit-lib v1.11.0 with @aws-sdk/client-cloudformation 3.938.0 installed alongside
Call CloudFormationStack.lookup() with a non-existent stack name
Observe that the ValidationError is thrown instead of returning a non-existent stack
Possible Solution
Update lib/util/format-error.js to handle AWS SDK v3 error structure:
function formatErrorMessage(error) {
if (error && Array.isArray(error.errors)) {
const innerMessages = error.errors
.map((innerError) => (innerError?.message || innerError?.toString()))
.join('\n');
return `AggregateError: ${innerMessages}`;
}
if (toolkit_error_1.ToolkitError.isToolkitError(error) && error.cause) {
return `${error.message}\n${formatErrorMessage(error.cause)}`;
}
// AWS SDK v3 structure: check error.Error.Message first
if (error && typeof error === 'object' && 'Error' in error &&
error.Error && typeof error.Error === 'object' && 'Message' in error.Error) {
return error.Error.Message;
}
// Fallback for regular Error or other types
return error?.message || error?.toString() || 'Unknown error';
}
Also update lib/api/cloudformation/stack-helper.js to remove the incorrect Error name check
static async lookup(cfn, stackName, retrieveProcessedTemplate = false) {
try {
const response = await cfn.describeStacks({ StackName: stackName });
return new CloudFormationStack(cfn, stackName, response.Stacks && response.Stacks[0], retrieveProcessedTemplate);
}
catch (e) {
const errorMessage = (0, util_1.formatErrorMessage)(e);
if (errorMessage === `Stack with id ${stackName} does not exist`) { // Remove check on e.name === 'ValidationError'
return new CloudFormationStack(cfn, stackName, undefined);
}
throw e;
}
}
Additional Information/Context
This issue affects all AWS SDK v3 service exceptions that use the nested Error.Message structure, not just ValidationError. The fix should be applied to ensure compatibility with AWS SDK v3 across all error types.
CDK CLI Version
xxx
Framework Version
1.11.0
Node.js Version
24.11.1
OS
MacOS 15.7.1
Language
TypeScript
Language Version
No response
Other information
No response