Skip to content

oauth/xai: Retry-After HTTP-date and fractional-second forms are ignored in postXaiToken #4046

Closed

Description

@lidge-jun

Where

src/oauth/xai.ts line 98 (retryDelay), on dev:

seconds=retryAfter!==null&&/^\d+$/.test(retryAfter)?Number(retryAfter):0

Problem

RFC 9110 §10.2.3 allows Retry-After as either delay-seconds or an HTTP-date. The regex accepts integer seconds only, so an HTTP-date (Retry-After: Sun, 06 Nov 1994 08:49:37 GMT) or a fractional value (1.5) becomes seconds = 0 and the server instruction is silently dropped; the client falls back to the 100/250ms jittered base delay.

Measured on Node 24:

retryDelay(1, "Sun, 06 Nov 1994 08:49:37 GMT", () => 0.5)  ->  100
retryDelay(1, "1.5", () => 0.5)                              ->  100

Fix

Parse as number first, then fall back to Date.parse:

function parseRetryAfterMs(raw: string | null): number | undefined {
  if (!raw) return undefined;
  const n = Number(raw);
  if (Number.isFinite(n)) return Math.max(0, n * 1000);
  const t = Date.parse(raw);
  return Number.isFinite(t) ? Math.max(0, t - Date.now()) : undefined;
}

Found while porting this module into ima2-gen (devlog 260909_grok_native_oauth/001_opencodex_port_spec.md D2). Independent of the 2000ms cap issue but the same function.

Activity

  1. added
    bugSomething isn't working
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    on Sep 8, 2026
  2. lidge-jun commented on Sep 8, 2026

    @lidge-jun
    OwnerAuthor

    리뷰 · 우선순위 52 / 80

    이 이슈는 같은 retryDelay가 Retry-After의 정수 초만 읽고, HTTP-date·소수 초는 조용히 무시한다는 이야기입니다. 지금 dev HEAD cfff026 src/oauth/xai.ts 98행 근처는 대략 이렇게 파싱합니다.

    seconds = retryAfter !== null && /^\d+$/.test(retryAfter) ? Number(retryAfter) : 0

    RFC 9110 §10.2.3는 delay-seconds와 HTTP-date 둘 다 허용합니다. 정규식이 ^\d+$만 받으니 Sun, 06 Nov 1994 08:49:37 GMT나 1.5는 seconds = 0이 되고, 클라이언트는 100/250ms 지터 폴백으로 바로 재시도합니다. 이슈 측정값도 date/fractional 모두 폴백(100)입니다.

    #4045(2초 캡)와 같은 함수·같은 호출 자리입니다. 다만 실제 auth.x.ai가 정수 초를 주로 준다면 체감 빈도는 #4045보다 낮습니다. 그래도 파서가 스펙의 절반만 구현한 상태라, 캡을 고치면서 같이 고치지 않으면 다음에 또 발에 걸립니다. 패키지 2.49.0 xAI OAuth 경로(postXaiToken)에만 영향이고, types/config 분할과 무관합니다.

    제안된 parseRetryAfterMs는 숫자면 초→ms, 아니면 Date.parse로 남은 ms를 계산합니다. 음수·NaN 가드만 있으면 충분해 보입니다. #4045의 절대 천장(예: 60s)을 여기에도 같이 걸면 됩니다.

    라인 98 · retryDelay 파싱 - /^\d+$/만 통과시켜 HTTP-date·소수를 버립니다. 스펙과 코드가 어긋납니다.

    경로 Date.parse 폴백 - 과거 날짜면 0ms가 되어 즉시 재시도합니다. “파싱 실패”와 “이미 지난 시각”을 구분할지는 선택입니다.

    경로 #4045와의 겹침 - 캡만 고치고 파서를 안 고치면, date 형태 Retry-After는 여전히 폴백입니다. 한 함수·한 PR이 자연스럽습니다.

    메인테이너의 판단이 필요한 지점

    • 소수 초(1.5)를 공식 지원할지, 정수+HTTP-date만 할지
    • 과거 HTTP-date를 0으로 클램할지, 파싱 실패로 폴백할지
    • #4045와 동일 PR로 묶을지

    너의 추천
    수락하되 #4045와 한 PR로 묶는 쪽을 추천합니다. 단독 우선순위는 중간입니다. 단위 테스트에 date·fractional·정수 세 케이스를 넣으세요.

    이 댓글은 grok-bot이 작성했습니다

  3. lidge-jun commented on Sep 9, 2026

    @lidge-jun
    OwnerAuthor

    Fixed on dev via #4087 at 4a08c75.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingproviderProvider adapters, OpenAI-compat presets, upstream API quirks

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions