{"record":{"id":"077220c6882dff7f","repo":"pulumi/pulumi","slug":"leakmessage","errorCode":null,"errorMessage":"${leakMessage}","messagePattern":"\\$\\{leakMessage\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"sdk/nodejs/automation/server.ts","lineNumber":46,"sourceCode":" * @internal\n */\nexport class LanguageServer<T> implements grpc.UntypedServiceImplementation {\n    readonly program: () => Promise<T>;\n\n    // Satisfy the grpc.UntypedServiceImplementation interface.\n    [name: string]: any;\n\n    constructor(program: () => Promise<T>) {\n        this.program = program;\n    }\n\n    onPulumiExit(hasError: boolean) {\n        // Check for leaks once the CLI exits but skip if the program otherwise\n        // errored to keep error output clean\n        if (!hasError) {\n            const [leaks, leakMessage] = debuggable.leakedPromises();\n            if (leaks.size !== 0) {\n                throw new Error(leakMessage);\n            }\n        }\n    }\n\n    getRequiredPlugins(call: any, callback: any): void {\n        const resp: any = new langproto.GetRequiredPluginsResponse();\n        resp.setPluginsList([]);\n        callback(undefined, resp);\n    }\n\n    run(call: any, callback: any): Promise<void> {\n        const req: any = call.request;\n        const resp: any = new langproto.RunResponse();\n\n        // Setup a new async state store for this run\n        return localState.withLocalStorage(async () => {\n            const errorSet = new Set<Error>();\n            const uncaughtHandler = newUncaughtHandler(errorSet);","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/nodejs/automation/server.ts#L28-L64","documentation":"After the Pulumi CLI process exits, the language server checks debuggable.leakedPromises() for promises that were never awaited. If the program exited cleanly but promises leaked (indicating work that silently never completed), the server throws with a diagnostic message describing the leaks. This is suppressed when the program already errored to keep output clean.","triggerScenarios":"A Node.js Pulumi program registers a promise (e.g. an un-awaited async call or .then chain) that is still pending/unhandled when the program finishes; onPulumiExit then throws with the leak report.","commonSituations":"Forgetting to await an output.apply side effect or an async function call in the program; fire-and-forget operations like exports of unresolved values.","solutions":["Await every promise created in the program, especially inside apply callbacks.","Check the leakMessage for the stack trace identifying the un-awaited call site.","Enable promise-leak debugging by following the message's pointer to where the promise was created."],"exampleFix":"// before\nbucket.onObjectCreated('handler', handler); // returns promise, not awaited\n// after\nconst done = bucket.onObjectCreated('handler', handler);\nawait done; // or ensure it resolves before program end","handlingStrategy":"try-catch","validationCode":"process.on('unhandledRejection', (r) => console.error('leaked promise:', r));","typeGuard":null,"tryCatchPattern":"try { await program(); } catch (e) { if (String(e.message).includes('leaked')) { console.error(e.message); process.exitCode = 1; } else throw e; }","preventionTips":["Await every async call in the Pulumi program","Enable strict mode and no-floating-promises ESLint rule","Run with --stack-trace-limit high enough to see leak origins"],"tags":["typescript","nodejs","promise","async"],"backgroundTag":"unhandled-promise-leak","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}