Where
src/oauth/xai.ts line 98 (retryDelay), on dev (blob f876b18):
return Math.min(2000,Math.max(j,seconds*1000));
Problem
Math.min(2000, ...) wraps the server-provided Retry-After value, so any delay the token endpoint asks for is truncated to 2 seconds. Measured on Node 24 with the function extracted verbatim:
retryDelay(2, "60", () => 0.5) -> 2000
When auth.x.ai answers 429 with Retry-After: 60, postXaiToken sleeps 2s, hits 429 again, and burns all 3 attempts in ~4s instead of honoring the server. RFC 9110 §10.2.3 treats Retry-After as a value to honor, not a ceiling to clamp.
Fix
Apply the 2000ms cap to the jitter only, and honor Retry-After (with a generous absolute ceiling such as 60s to avoid pathological values):
if (seconds > 0) return Math.min(seconds * 1000, 60_000);
return Math.min(2000, j);
Repro
const random = () => 0.5;
retryDelay(1, "60", random); // expected 60000, got 2000
Found while porting this module into ima2-gen (devlog 260909_grok_native_oauth/001_opencodex_port_spec.md D1). Related: the HTTP-date form of Retry-After is also ignored (separate issue).
Where
src/oauth/xai.tsline 98 (retryDelay), ondev(blobf876b18):Problem
Math.min(2000, ...)wraps the server-providedRetry-Aftervalue, so any delay the token endpoint asks for is truncated to 2 seconds. Measured on Node 24 with the function extracted verbatim:When
auth.x.aianswers429withRetry-After: 60,postXaiTokensleeps 2s, hits 429 again, and burns all 3 attempts in ~4s instead of honoring the server. RFC 9110 §10.2.3 treatsRetry-Afteras a value to honor, not a ceiling to clamp.Fix
Apply the 2000ms cap to the jitter only, and honor
Retry-After(with a generous absolute ceiling such as 60s to avoid pathological values):Repro
Found while porting this module into ima2-gen (devlog
260909_grok_native_oauth/001_opencodex_port_spec.mdD1). Related: the HTTP-date form of Retry-After is also ignored (separate issue).