Skip to content

design/src/variants.ts: 429 retry path ignores Retry-After header #1244

@SirBrenton

Description

@SirBrenton

429 handler in generateVariant() ignores Retry-After header, causing premature retries

In generateVariant(), the 429 handler detects rate limiting but does not inspect the Retry-After header:

ts if (response.status === 429) {   lastError = "Rate limited (429)";   continue; } 

Because retry delay is controlled by the local exponential schedule, the code retries after 2s / 4s / 8s even if the provider asked the client to wait longer. In image generation batches, this can burn all attempts inside the provider cooldown window.

Given gstack’s skill architecture, this likely belongs in design/src/variants.ts, followed by the normal rebuild/test path for generated skill output.


Expected behavior

  • Read Retry-After when present
  • Wait for the provider-supplied delay
  • Fall back to exponential backoff only when the header is missing

Suggested fix

ts if (response.status === 429) {   const retryAfter = response.headers.get("retry-after");    if (retryAfter) {     const parsed = Number.parseInt(retryAfter, 10);      if (!Number.isNaN(parsed) && parsed > 0) {       await new Promise((resolve) => setTimeout(resolve, parsed * 1000));       continue;     }   }    lastError = "Rate limited (429)";   continue; } 

Context

This is a common failure pattern where the 429 status is handled but the Retry-After header is not consulted for the retry decision.

Related pattern: retry-after-ignored-under-concurrency
Corpus reference: https://github.com/SirBrenton/pitstop-truth

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions