From 7f755913a60db8d4e7c1959b4cf397756c14f3d7 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 28 May 2026 05:23:27 +0000 Subject: [PATCH] fix(cli): print the update-available notice once, not on every event-loop drain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `process.on("beforeExit", ...)` re-fires every time the event loop drains, and the handler kicks off a fire-and-forget async telemetry flush — so on a successful command the user sees the "Update available: …" notice twice (once after the initial drain, again after the flush settles). Using `process.once` detaches the listener after first invocation, fixing the double-print and also preventing a double-flush of telemetry. Reported during local testing of `auth login`, but the bug affects every command (any path where `_flush()` schedules work). --- packages/cli/src/cli.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 1e414b684..34755f5a9 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -193,8 +193,12 @@ if (!isHelp && !hasJsonFlag && command !== "upgrade") { const commandStart = Date.now(); let commandFailed = false; -// Async flush for normal exit (beforeExit fires when the event loop drains) -process.on("beforeExit", () => { +// Async flush for normal exit. `beforeExit` re-fires every time the +// event loop drains, and the async `_flush()` itself schedules new +// work — so a plain `on` listener would print the update notice (and +// re-flush) once per drain (the user-reported double-print). `once` +// detaches after first invocation, which is what we want for both. +process.once("beforeExit", () => { _flush?.().catch(() => {}); if (!hasJsonFlag) _printUpdateNotice?.(); });