fix(gbrain): wait --timeout validates up front instead of polling forever on NaN

Number('abc') is NaN, NaN comparisons are always false, and the
poll loop never hit its deadline — an infinite 5s loop where the bash
predecessor errored immediately. die(2) at parse time, with a test.
This commit is contained in:
Garry Tan 2026-08-15 16:49:39 -07:00
parent f6e3297b3d
commit fd47cd8477
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
2 changed files with 18 additions and 1 deletions

View File

@ -411,6 +411,12 @@ async function cmdWait(ctx: Ctx, args: string[]): Promise<void> {
else ref = arg;
}
if (!ref) die(ctx, 'wait: missing <ref>');
// Validate up front: NaN would make the deadline comparison below always
// false and the poll loop run forever (the bash predecessor errored here).
const timeoutSeconds = Number(timeout);
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds < 0) {
die(ctx, 'wait: --timeout must be a non-negative integer (seconds)');
}
requirePat(ctx);
@ -439,7 +445,7 @@ async function cmdWait(ctx: Ctx, args: string[]): Promise<void> {
ctx.stderr(`${PROG}: unexpected status '${status}' — continuing to poll\n`);
}
if (elapsed >= Number(timeout)) {
if (elapsed >= timeoutSeconds) {
ctx.stderr(`${PROG}: wait timed out after ${timeout}s (last status: ${status})\n`);
ctx.stderr(`${PROG}: re-run with /setup-gbrain --resume-provision ${ref}\n`);
throw new ExitError(6);

View File

@ -360,6 +360,17 @@ describe('wait', () => {
expect(r.stderr).toContain('wait timed out');
expect(r.stderr).toContain('--resume-provision abc');
});
test('non-numeric --timeout dies at parse time instead of polling forever', async () => {
// NaN would make `elapsed >= timeout` always false: an infinite 5s poll loop.
// The bash predecessor errored on `[ "$elapsed" -ge "abc" ]`; the port
// must be at least as strict.
const r = await runCmd(['wait', 'abc', '--timeout', 'abc'], {
SUPABASE_ACCESS_TOKEN: 'sbp_test',
});
expect(r.status).toBe(2);
expect(r.stderr).toContain('--timeout must be a non-negative integer');
});
});
describe('pooler-url', () => {