Repository navigation
sentry 0.45.0 library commands retain SIGTERM listeners under VERCEL #1692
Description
sentry 0.45.0 library commands retain SIGTERM listeners under VERCEL
Fault
Repeated in-process library commands add SIGTERM handlers under VERCEL. The source-map uploader in @sentry/nextjs 11.8.0 uses this API. Bite's Vercel builds report 11 SIGTERM listeners during the client pass, while source-map uploads still succeed.
Reproduction and measured results
Measured 2026-10-28 on Linux x64, Node 24.18.0, locked sentry 0.45.0 from Bite Preview edfe7a74938b87fc8dc366b9227ffb6bdb3ffd08. A fresh process performs 15 successful sdk.sourcemap.inject({directory}) calls on synthetic JavaScript and a source map; a second fresh process repeats with VERCEL=1. Both verify the injected debugId= marker. No auth token or DSN is needed for injection.
- Without VERCEL: SIGTERM counts remain 0 after every completed call; adds 0, removals 0, warnings 0.
- With VERCEL=1: counts rise 1 through 15 after completed calls; adds 15, removals 0; the actual MaxListenersExceededWarning occurs at 11.
- Both source-map injection sequences succeed. This establishes retention after sequential completion, not just overlapping live operations.
- Executed through the repaired Quantum host gate after >=120 seconds of uninterrupted CPU<40%, no competing workloads, available memory>=8192 MiB; command exit 0. Full gate samples and registration stacks retained outside Git. Initial pre-repair attempt was stopped before any reproduction ran because the matcher missed node-24; that host defect is tracked separately in getsliced/bite#1065. No telemetry setting is changed, the default listener limit stays 10, and no warning is suppressed.
Source ownership
- @sentry/bundler-plugins 11.8.0
src/core/cli.ts: SentryCliAdapter uses createSentrySDK; source-map inject/upload, release operations and getServerUrl invoke library commands in the build process. - sentry 0.45.0
packages/cli/src/lib/sdk-invoke.tsexecuteWithCapture calls withTelemetry in library mode for each command, then flushes telemetry. packages/cli/src/lib/telemetry.tswithTelemetry calls initSentry per invocation. initSentry calls getClient()?.close(0) before Sentry.init.- sentry 0.45.0 bundles @sentry/node-core 10.63.0. Its
packages/node-core/src/light/sdk.ts:129-136registers an anonymous process.on('SIGTERM') handler per init when process.env.VERCEL is set. The handler closes over that client, with no paired removal in this path. - The installed sentry/dist/index.cjs contains the same branch. Bite's top-level @sentry/node 11.8.0 has a separate singleton Vercel handler; changing only that top-level package does not replace the CLI's bundled code.
Sources:
https://github.com/getsentry/cli/blob/03f636f8d1fe6553acf22595eb029ddc8efc79eb/packages/cli/src/lib/sdk-invoke.ts
https://github.com/getsentry/cli/blob/03f636f8d1fe6553acf22595eb029ddc8efc79eb/packages/cli/src/lib/telemetry.ts
https://github.com/getsentry/cli/blob/03f636f8d1fe6553acf22595eb029ddc8efc79eb/packages/cli/package.json
https://github.com/getsentry/sentry-javascript/blob/10.63.0/packages/node-core/src/light/sdk.ts#L129-L136
Requested upstream repair and acceptance
Manage the bundled SDK's Vercel listener lifecycle across library invocations, preserving telemetry and signal flushing. Verify successful and failed sequential library commands leave bounded listener counts, actual repeated inject/upload operations succeed, and a Next.js webpack build under VERCEL no longer warns while uploading all client/server/edge maps. A newer top-level SDK alone cannot update the already-bundled CLI SDK. No performance claim is made from these logs.
Scope and limits
Bite is unchanged. This report does not prove a fixed uploader or a new successful authenticated upload; existing build observations show successful uploads with the warning. Local credentials for authenticated uploads are absent. Do not increase the global listener limit or disable telemetry/source maps as a workaround.
Related upstream work: getsentry/sentry-javascript#25146 addresses repeated init in the newer Node SDK. This report concerns the older node-core/light code embedded in sentry 0.45.0, independently of the app's installed SDK. The CLI package manifest at the inspected current toolkit commit 8860f39 still lists node-core 10.63.0; no runtime assertion about an unreleased toolkit build is made.
Reproduction script
This reproduction targets Linux/POSIX and hardcodes /tmp. Save as lifecycle.cjs in a project with sentry@0.45.0 installed, then run node lifecycle.cjs (the child processes enable --trace-warnings). No credentials are required. Exit 0 confirms command completion and a detected injection marker; listener counts and warning counts are reported, not asserted.
const { createRequire } = require('node:module');
const { spawnSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
const req = createRequire(process.cwd() + '/package.json');
if (!process.argv.includes('--scenario')) {
for (const vercel of [false, true]) {
const env = { ...process.env };
delete env.VERCEL;
if (vercel) env.VERCEL = '1';
const child = spawnSync(process.execPath, ['--trace-warnings', __filename, '--scenario'], { env, stdio: 'inherit' });
if (child.status !== 0) process.exit(child.status || 1);
}
} else {
const events = [];
const counts = [];
let warnings = 0;
process.on('newListener', (name) => {
if (name === 'SIGTERM') events.push({ kind: 'add', count: process.listenerCount(name) + 1, stack: new Error('SIGTERM registration').stack });
});
process.on('removeListener', (name) => {
if (name === 'SIGTERM') events.push({ kind: 'remove', count: process.listenerCount(name) });
});
process.on('warning', (warning) => {
if (warning.name === 'MaxListenersExceededWarning') {
warnings++;
console.log('WARNING', warning.stack);
}
});
(async () => {
const { createSentrySDK } = req('sentry');
const fixture = fs.mkdtempSync('/tmp/bite-893-inject-');
const js = path.join(fixture, 'example.js');
fs.writeFileSync(js, 'console.log("synthetic source-map fixture");\n//# sourceMappingURL=example.js.map\n');
fs.writeFileSync(js + '.map', JSON.stringify({ version: 3, sources: ['example.ts'], sourcesContent: ['console.log("synthetic source-map fixture");'], names: [], mappings: 'AAAA', file: 'example.js' }));
const sdk = createSentrySDK({ cwd: fixture });
const start = process.listenerCount('SIGTERM');
console.log('SCENARIO', JSON.stringify({ vercel: !!process.env.VERCEL, start, maxListeners: process.getMaxListeners() }));
for (let i = 1; i <= 15; i++) {
// This is a real source-map operation used by SentryCliAdapter; no token required.
await sdk.sourcemap.inject({ directory: fixture });
counts.push(process.listenerCount('SIGTERM'));
}
await new Promise(resolve => setImmediate(resolve));
const injected = fs.readFileSync(js, 'utf8').includes('debugId=');
console.log('RESULT', JSON.stringify({ vercel: !!process.env.VERCEL, start, counts, warnings, injected, adds: events.filter(e => e.kind === 'add').length, removes: events.filter(e => e.kind === 'remove').length }));
console.log('EVENTS', JSON.stringify(events, null, 2));
if (!injected) process.exitCode = 1;
})().catch(error => { console.error(error); process.exitCode = 1; });
}The warning stack begins:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGTERM listeners added to [process]. MaxListeners is 10.
at process.addListener (node:events:608:10)
at Afe (<project>/node_modules/sentry/dist/index.cjs:85:2404)
at zP (<project>/node_modules/sentry/dist/index.cjs:85:1815)
at mEe (<project>/node_modules/sentry/dist/index.cjs:204:4244)
at hTt (<project>/node_modules/sentry/dist/index.cjs:204:2230)
at bat (<project>/node_modules/sentry/dist/index.cjs:7328:7736)
Downstream build observations (successful uploads alongside this warning): https://github.com/getsliced/bite/issues/893 . They do not establish fixed behavior, and the minimal reproduction above sends no source-map network upload.
Activity
linear-code commentedon Oct 28, 2026
MCP-1131
fix(cli): Drop stale SDK SIGTERM listeners on telemetry re-init
fix(cli): Move the CLI to Sentry SDK v11 and its defaults (#1694)
fix(v10/node-core): Register the Vercel SIGTERM listener once (#25826)