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
429 handler in generateVariant() ignores Retry-After header, causing premature retries
In
generateVariant(), the 429 handler detects rate limiting but does not inspect theRetry-Afterheader: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
Retry-Afterwhen presentSuggested fix
Context
This is a common failure pattern where the 429 status is handled but the
Retry-Afterheader is not consulted for the retry decision.Related pattern:
retry-after-ignored-under-concurrencyCorpus reference: https://github.com/SirBrenton/pitstop-truth