What happens
The CLI entrypoint parses argv with the synchronous Command.parse():
// packages/cli/src/index.ts
if (detectIsMainModule()) {
createProgram().parse(normalizeLegacyArgs(process.argv));
}
But every command action is wired as async in base.command.ts:
command.action(async (...data) => {
...
await this.action({ args, options: commandOptions });
});
.parse() does not await the promise returned by an async action, and there is no top-level handler. So when an action rejects — e.g. a failed OAuth token exchange during corsair setup, or a network error in watch-renew — Node prints a raw UnhandledPromiseRejection stack trace instead of the clean [#corsair]: ... diagnostic the rest of the CLI uses (12 call sites, e.g. utils/corsair-instance.ts).
Impact
Confusing UX on every failing command; the process can also exit 0 on older Node versions before the rejection is reported. Affects setup, auth, list, schema, watch-renew, studio, script, and the subscribe commands.
Expected
A rejecting action should print a single [#corsair]: <message> line and exit non-zero.
Fix
Use .parseAsync() with a top-level .catch(). Commander already handles its own parse/help/version exits synchronously, so this only affects genuine action errors. PR attached.
What happens
The CLI entrypoint parses argv with the synchronous
Command.parse():But every command action is wired as
asyncinbase.command.ts:.parse()does not await the promise returned by an async action, and there is no top-level handler. So when an action rejects — e.g. a failed OAuth token exchange duringcorsair setup, or a network error inwatch-renew— Node prints a rawUnhandledPromiseRejectionstack trace instead of the clean[#corsair]: ...diagnostic the rest of the CLI uses (12 call sites, e.g.utils/corsair-instance.ts).Impact
Confusing UX on every failing command; the process can also exit
0on older Node versions before the rejection is reported. Affectssetup,auth,list,schema,watch-renew,studio,script, and the subscribe commands.Expected
A rejecting action should print a single
[#corsair]: <message>line and exit non-zero.Fix
Use
.parseAsync()with a top-level.catch(). Commander already handles its own parse/help/version exits synchronously, so this only affects genuine action errors. PR attached.