diff --git a/src/cli.ts b/src/cli.ts index 29a3e961e..02802d901 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -330,6 +330,13 @@ function pm2Capture(args: string[], home: string = PM2_HOME, timeoutMs = 10_000) env: pm2Env(home), shell: pm2.shell ?? false, timeout: timeoutMs, + // `pm2 jlist` serializes EVERY process's full env + metadata, so its stdout + // grows ~linearly with the bot count. Node's default spawnSync maxBuffer is + // 1 MiB — a box with ~30+ bots blows past it and spawnSync fails with + // ENOBUFS, which surfaced as `start-bot` (dashboard "bring one bot online") + // dying before it could launch anything. Lift the cap well above any real + // fleet size. (ps/git captures elsewhere already do the same.) + maxBuffer: 64 * 1024 * 1024, }); if (r.status !== 0) { const detail = r.error?.message diff --git a/src/core/plugins/pm2.ts b/src/core/plugins/pm2.ts index e87f1a74e..b62a30039 100644 --- a/src/core/plugins/pm2.ts +++ b/src/core/plugins/pm2.ts @@ -56,6 +56,10 @@ export function capturePluginPm2(args: string[], opts: { timeoutMs?: number; env env: pm2Env(opts.env), shell: pm2.shell ?? false, timeout: opts.timeoutMs ?? 10_000, + // `pm2 jlist` output scales with the process count (full env per process); + // Node's 1 MiB default spawnSync buffer overflows to ENOBUFS on large + // fleets. Match cli.ts pm2Capture — lift the cap far above any real size. + maxBuffer: 64 * 1024 * 1024, }); if (result.status !== 0) { const detail = result.error?.message