api resource_error ai_generated partial

429 Too Many Requests: Retry-After header value is malformed or missing

ID: api/rate-limit-exceeded-retry-after-malformed

Also available as: JSON · Markdown · 中文
70%Fix Rate
80%Confidence
1Evidence
2024-08-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Nginx 1.24.0 active
Cloudflare 2024 active
AWS API Gateway 2024 active
Kong 3.5.0 active

Root Cause

Server returns 429 with a Retry-After header that has an invalid format (e.g., non-numeric, negative, or missing entirely), causing clients to fail to implement proper backoff.

generic

中文

服务器返回429,但Retry-After头格式无效(例如非数字、负数或完全缺失),导致客户端无法实现正确的退避。

Official Documentation

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After

Workarounds

  1. 85% success Implement robust Retry-After parsing that handles both seconds and HTTP-date formats: `const retryAfter = response.headers.get('Retry-After'); let delay; if (retryAfter && /^\d+$/.test(retryAfter)) { delay = parseInt(retryAfter) * 1000; } else if (retryAfter) { delay = new Date(retryAfter).getTime() - Date.now(); } else { delay = 5000; }`
    Implement robust Retry-After parsing that handles both seconds and HTTP-date formats: `const retryAfter = response.headers.get('Retry-After'); let delay; if (retryAfter && /^\d+$/.test(retryAfter)) { delay = parseInt(retryAfter) * 1000; } else if (retryAfter) { delay = new Date(retryAfter).getTime() - Date.now(); } else { delay = 5000; }`
  2. 80% success Use exponential backoff with jitter as fallback when Retry-After is missing: `delay = Math.min(60000, Math.pow(2, attempt) * 1000 + Math.random() * 1000)`
    Use exponential backoff with jitter as fallback when Retry-After is missing: `delay = Math.min(60000, Math.pow(2, attempt) * 1000 + Math.random() * 1000)`
  3. 70% success Contact API provider to fix Retry-After header format, and in the meantime, parse it leniently (e.g., extract first numeric value)
    Contact API provider to fix Retry-After header format, and in the meantime, parse it leniently (e.g., extract first numeric value)

中文步骤

  1. 实现健壮的Retry-After解析,处理秒数和HTTP日期格式:`const retryAfter = response.headers.get('Retry-After'); let delay; if (retryAfter && /^\d+$/.test(retryAfter)) { delay = parseInt(retryAfter) * 1000; } else if (retryAfter) { delay = new Date(retryAfter).getTime() - Date.now(); } else { delay = 5000; }`
  2. 当Retry-After缺失时,使用带抖动的指数退避作为回退:`delay = Math.min(60000, Math.pow(2, attempt) * 1000 + Math.random() * 1000)`
  3. 联系API提供商修复Retry-After头格式,同时宽松解析(例如提取第一个数值)

Dead Ends

Common approaches that don't work:

  1. 80% fail

    Hardcoding a fixed retry delay (e.g., 5 seconds) instead of parsing Retry-After

  2. 90% fail

    Ignoring Retry-After and retrying immediately, causing repeated 429 responses

  3. 65% fail

    Assuming Retry-After is always in seconds (when it could be an HTTP-date)