Skip to content

Commit e8e304a

Browse files
committed
chore: overwrite $CDK_ERROR_FILE on every Error
To go with our changes in aws/aws-cdk-cli#1294: We can no longer scan `stderr` to find the actual terminating error code. Best we can do then is guess that it is probably the most recently thrown error. We will therefore replace the file on every new `Error` creation, leaving the last error to be found there if the subprocess happens to exit with an error code.
1 parent 09e3daf commit e8e304a

File tree

2 files changed

+14
-24
lines changed

2 files changed

+14
-24
lines changed

packages/aws-cdk-lib/core/lib/errors.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -264,38 +264,28 @@ export function renderConstructRootPath(construct: IConstruct) {
264264
return ret.join('\n');
265265
}
266266

267-
const THROWN_ERRORS = new Set<string>();
268-
269267
/**
270-
* If the appropriate environment variable is set, write this error code to a list of error codes in the given file.
271-
*
272-
* The reason we do this is so that the CLI can scan `stderr` for one of the
273-
* error codes between markers, and be confident that when it finds something
274-
* that it's not user content but an actual error we threw.
268+
* If the appropriate environment variable is set, write this error code the given file.
275269
*
276-
* - Why not just scan `stderr`? Because customers could put customer content
277-
* between those markers, and we would capture user content as an error code (we
278-
* explicitly don't want to do that!)
270+
* The reason we do this is so that the CLI can see the error code that led to the
271+
* termination of the CDK application.
279272
*
280-
* - Why not take the error code immediately? Because the error could have been
281-
* caught; but we only want to capture the error that terminated the program.
273+
* This is not a guarantee: this exception could be caught and a different one
274+
* thrown in its stead, in which case we would pick up the wrong error code.
275+
* We will take that risk, and assume such cases are rare. The CLI only looks
276+
* at the error file if the subprocess terminates with an error, and the most
277+
* likely culprit in that case is the most recently thrown error regardless.
282278
*
283-
* So we're doing a double whammy of writing potential error codes to a file, then
284-
* make sure that we find that error code in `stderr`.
279+
* Why not use `process.onUncaughtException()`? That will work for pure Node
280+
* programs, but in a jsii language no exception is uncaught (the kernel
281+
* is always the outermost loop) so that event handler would never fire.
285282
*/
286283
function maybeWriteErrorCode(errorCode: string) {
287284
const file = process.env.CDK_ERROR_FILE;
288285
if (!file) {
289286
return;
290287
}
291288

292-
// Only if this error is new
293-
const oldSize = THROWN_ERRORS.size;
294-
THROWN_ERRORS.add(errorCode);
295-
if (THROWN_ERRORS.size === oldSize) {
296-
return;
297-
}
298-
299289
// Update the indicated file
300-
fs.writeFileSync(file, Array.from(THROWN_ERRORS).sort().join('\n'), 'utf-8');
290+
fs.writeFileSync(file, errorCode, 'utf-8');
301291
}

packages/aws-cdk-lib/core/test/errors.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Relates to construct:
8787
}
8888
});
8989

90-
test('writing error codes to disk', async () => {
90+
test('most recent error codes is written to disk', async () => {
9191
const file = path.join(os.tmpdir(), 'errors.txt');
9292
await rm(file, { force: true });
9393
try {
@@ -103,7 +103,7 @@ Relates to construct:
103103
throw new UnscopedValidationError('Error2', 'bla');
104104
} catch { }
105105
const contents2 = await readFile(file, 'utf-8');
106-
expect(contents2).toEqual('Error1\nError2');
106+
expect(contents2).toEqual('Error2');
107107
} finally {
108108
delete process.env.CDK_ERROR_FILE;
109109
await rm(file, { force: true });

0 commit comments

Comments
 (0)