From 6065ddc6118b7805e0b5b120b0267bdb78fc3632 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 12 Jun 2026 15:18:28 +0200 Subject: [PATCH 1/2] feat: `--debug-app` enables jsii stack traces Recent Python and Java jsii clients can capture stack traces and send them to the JavaScript side, to end up in CDK stack captures. Because this has performance implications, this is not done by default but requires the environment variable `JSII_HOST_STACK_TRACES=1` to be set. `cdk --debug[-app]` will now set this environment variable if it isn't already set, so that in debug mode the stack traces are captured appropriately. We leave the environment variable alone if it's already set, so that the user can explicitly opt out of this behavior by setting it to `0` beforehand. --- .../lib/api/cloud-assembly/environment.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts index 7f8129090..40daa9aab 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts @@ -84,12 +84,25 @@ export function synthParametersFromSettings(settings: Settings): { context: Context; env: Env; } { + // These are the environment variables that will switch on debugging in the + // CDK framework. + // + // - CDK_DEBUG: an environment variable instead of a context variable, so it can also + // be accessed in framework code where we don't have access to a construct tree. + // - JSII_HOST_STACK_TRACES: have the jsii client library send call stacks + // across so we can read them in JS-land. Only set if not already set by the + // user, this allows them to switch it off by setting `JSII_HOST_STACK_TRACES=0`. + const debugEnvVars: Record = { + CDK_DEBUG: 'true', + }; + if (process.env.JSII_HOST_STACK_TRACES === undefined) { + debugEnvVars.JSII_HOST_STACK_TRACES = '1'; + } + return { context: contextFromSettings(settings), env: { - // An environment variable instead of a context variable, so it can also - // be accessed in framework code where we don't have access to a construct tree. - ...settings.get(['debugApp']) ? { CDK_DEBUG: 'true' } : {}, + ...settings.get(['debugApp']) ? debugEnvVars : {}, }, }; } From 9460b392418bdd724227a19442f8914c2b3c31f5 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 12 Jun 2026 15:24:38 +0200 Subject: [PATCH 2/2] Add test --- .../test/api/cloud-assembly/environment.test.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts index 1a921231d..3e27e50c9 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts @@ -30,7 +30,7 @@ test.each([ ])('cmd=%p win=%p (stat=%p) exe=%p node=%p => %p', async (commandLine: string, isWindows: boolean, statFile: string, isExecutable: boolean | undefined, nodePath: string, expected: string) => { // GIVEN process.execPath = nodePath; - Object.defineProperty(process, 'platform', { value: isWindows ? 'win32' : 'linux' }) ; + Object.defineProperty(process, 'platform', { value: isWindows ? 'win32' : 'linux' }); jest.spyOn(fs, 'stat').mockImplementation((p) => { if (p !== statFile) { throw new Error(`Expected a stat() call on '${statFile}' but got '${p}'`); @@ -98,4 +98,17 @@ describe('synthParametersFromSettings sets CDK_DEBUG from debugApp', () => { const { env } = synthParametersFromSettings(new Settings({})); expect(env.CDK_DEBUG).toBeUndefined(); }); + + test('debugApp: true sets JSII_HOST_STACK_TRACES', () => { + delete process.env.JSII_HOST_STACK_TRACES; + const { env } = synthParametersFromSettings(new Settings({ debugApp: true })); + expect(env.JSII_HOST_STACK_TRACES).toBe('1'); + }); + + test('debugApp: true does set JSII_HOST_STACK_TRACES if already set', () => { + process.env.JSII_HOST_STACK_TRACES = '0'; + const { env } = synthParametersFromSettings(new Settings({ debugApp: true })); + expect(Object.keys(env)).not.toContain('JSII_HOST_STACK_TRACES'); + delete process.env.JSII_HOST_STACK_TRACES; + }); });