You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(lambda): improve validation errors for lambda functions (#32323)
### Issue # (if applicable)
Relates to #32324
### Reason for this change
Currently all errors are untyped. This makes it difficult users to programmatically distinguish between different classes of errors, e.g. what is a validation error vs what is a syntax error? With this change, users can catch errors and check their type before proceeding accordingly.
### Description of changes
Addition of a new Error type `ValidationError`. For now this error is used only in a single file. The intention is to extend this to all error cases. `ValidationError` extends an abstract `ConstructError` which also handles any improvements to error display.
`ConstructError` manipulates the stack trace to improve display. It's changing two things, both of which are based on a construct that is passed in on error creation. If not construct is passed, the error behaves as before.
1. Construct information is inserted as the first line of the stack trace.
2. The strack trace is captured from the point of _creation of the construct_. That is the class constructor call. This is achieved by passing the error's constructs into [Error.captureStackTrace](https://nodejs.org/docs/latest-v22.x/api/errors.html#errorcapturestacktracetargetobject-constructoropt). As a side effect, in many cases the "line of error" is not minified code anymore and thus doesn't ruin the error experience for users.
See comments for current vs future errors.
### Description of how you validated changes
Existing test. Manual testing of error cases.
### Checklist
- [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md)
----
*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@@ -1137,7 +1138,7 @@ export class Function extends FunctionBase {
1137
1138
1138
1139
if(props.filesystem){
1139
1140
if(!props.vpc){
1140
-
thrownewError('Cannot configure \'filesystem\' without configuring a VPC.');
1141
+
thrownewValidationError('Cannot configure \'filesystem\' without configuring a VPC.',this);
1141
1142
}
1142
1143
constconfig=props.filesystem.config;
1143
1144
if(config.dependency){
@@ -1201,7 +1202,7 @@ export class Function extends FunctionBase {
1201
1202
'LAMBDA_RUNTIME_DIR',
1202
1203
];
1203
1204
if(reservedEnvironmentVariables.includes(key)){
1204
-
thrownewError(`${key} environment variable is reserved by the lambda runtime and can not be set manually. See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html`);
1205
+
thrownewValidationError(`${key} environment variable is reserved by the lambda runtime and can not be set manually. See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html`,this);
1205
1206
}
1206
1207
this.environment[key]={ value, ...options};
1207
1208
returnthis;
@@ -1214,24 +1215,24 @@ export class Function extends FunctionBase {
thrownewError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LogFormat to '${LogFormat.JSON}', got '${props.logFormat}'.`);
1231
+
thrownewValidationError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LogFormat to '${LogFormat.JSON}', got '${props.logFormat}'.`,this);
thrownewError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LoggingFormat to '${LoggingFormat.JSON}', got '${props.loggingFormat}'.`);
1235
+
thrownewValidationError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LoggingFormat to '${LoggingFormat.JSON}', got '${props.loggingFormat}'.`,this);
1235
1236
}
1236
1237
}
1237
1238
@@ -1268,7 +1269,7 @@ export class Function extends FunctionBase {
1268
1269
*/
1269
1270
publicinvalidateVersionBasedOn(x: string){
1270
1271
if(Token.isUnresolved(x)){
1271
-
thrownewError('invalidateVersionOn: input may not contain unresolved tokens');
1272
+
thrownewValidationError('invalidateVersionOn: input may not contain unresolved tokens',this);
1272
1273
}
1273
1274
this.hashMixins.push(x);
1274
1275
}
@@ -1283,11 +1284,11 @@ export class Function extends FunctionBase {
thrownewError(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`);
1291
+
thrownewValidationError(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`,this);
1291
1292
}
1292
1293
1293
1294
// Currently no validations for compatible architectures since Lambda service
@@ -1398,8 +1399,8 @@ export class Function extends FunctionBase {
1398
1399
}
1399
1400
constenvKeys=Object.keys(this.environment);
1400
1401
if(envKeys.length!==0){
1401
-
thrownewError(`The function ${this.node.path} contains environment variables [${envKeys}] and is not compatible with Lambda@Edge. \
1402
-
Environment variables can be marked for removal when used in Lambda@Edge by setting the \'removeInEdge\' property in the \'addEnvironment()\' API.`);
1402
+
thrownewValidationError(`The function ${this.node.path} contains environment variables [${envKeys}] and is not compatible with Lambda@Edge. \
1403
+
Environment variables can be marked for removal when used in Lambda@Edge by setting the \'removeInEdge\' property in the \'addEnvironment()\' API.`,this);
1403
1404
}
1404
1405
1405
1406
return;
@@ -1435,19 +1436,19 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett
1435
1436
}
1436
1437
1437
1438
if(props.runtime===Runtime.FROM_IMAGE){
1438
-
thrownewError("ADOT Lambda layer can't be configured with container image package type");
1439
+
thrownewValidationError("ADOT Lambda layer can't be configured with container image package type",this);
1439
1440
}
1440
1441
1441
1442
// This is not the complete list of incompatible runtimes and layer types. We are only
1442
1443
// checking for common mistakes on a best-effort basis.
1443
1444
if(this.runtime===Runtime.GO_1_X){
1444
-
thrownewError('Runtime go1.x is not supported by the ADOT Lambda Go SDK');
1445
+
thrownewValidationError('Runtime go1.x is not supported by the ADOT Lambda Go SDK',this);
1445
1446
}
1446
1447
1447
1448
// The Runtime is Python and Adot is set it requires a different EXEC_WRAPPER than the other code bases.
@@ -1622,15 +1623,15 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett
1622
1623
Annotations.of(this).addWarningV2('@aws-cdk/aws-lambda:snapStartRequirePublish','SnapStart only support published Lambda versions. Ignore if function already have published versions');
1623
1624
1624
1625
if(!props.runtime.supportsSnapStart){
1625
-
thrownewError(`SnapStart currently not supported by runtime ${props.runtime.name}`);
1626
+
thrownewValidationError(`SnapStart currently not supported by runtime ${props.runtime.name}`,this);
1626
1627
}
1627
1628
1628
1629
if(props.filesystem){
1629
-
thrownewError('SnapStart is currently not supported using EFS');
1630
+
thrownewValidationError('SnapStart is currently not supported using EFS',this);
0 commit comments