shareAI-lab/learn-claude-code · error · RuntimeError
Max retries ({MAX_RETRIES}) exceeded
Error message
Max retries ({MAX_RETRIES}) exceeded What it means
The API-call retry loop handles overloaded/529 responses by sleeping with backoff and retrying, up to MAX_RETRIES attempts. If the provider is still returning overload errors after the final attempt, the loop exits and raises this RuntimeError — the caller has exhausted the configured retry budget against a persistently saturated upstream.
Source
Thrown at s15_integrated_harness/code.py:2071
if "ratelimit" in name or "429" in msg:
delay = retry_delay(attempt)
print(f" \033[33m[429] retry {attempt + 1}/{MAX_RETRIES} "
f"after {delay:.1f}s\033[0m")
time.sleep(delay)
continue
if "overloaded" in name or "529" in msg or "overloaded" in msg:
state.consecutive_529 += 1
if state.consecutive_529 >= MAX_CONSECUTIVE_529 and FALLBACK_MODEL:
state.current_model = FALLBACK_MODEL
state.consecutive_529 = 0
print(f" \033[31m[529] switching to {FALLBACK_MODEL}\033[0m")
delay = retry_delay(attempt)
print(f" \033[33m[529] retry {attempt + 1}/{MAX_RETRIES} "
f"after {delay:.1f}s\033[0m")
time.sleep(delay)
continue
raise
raise RuntimeError(f"Max retries ({MAX_RETRIES}) exceeded")
def is_prompt_too_long_error(e: Exception) -> bool:
msg = str(e).lower()
return (("prompt" in msg and "long" in msg)
or "context_length_exceeded" in msg
or "max_context_window" in msg)
# -- Background Tasks --
# Slow tools return a placeholder tool_result immediately. Their real output is
# later injected as a task_notification, so the main loop can keep moving.
_bg_counter = 0
background_tasks: dict[str, dict] = {}
background_results: dict[str, str] = {}
background_lock = threading.Lock()
View on GitHub (pinned to 985456f4ad)
Solutions
- Wait and retry at a coarser cadence (the incident is upstream); space out requests to reduce concurrent load.
- Raise MAX_RETRIES and/or the backoff curve (retry_delay) in config so the loop spans the incident.
- Configure a healthy FALLBACK_MODEL on a different provider/family so the 529 switch actually lands somewhere available.
- If self-hosting the gateway, check its rate limits — sustained 529-like responses can be your own proxy shedding load.
Example fix
// before MAX_RETRIES = 3 // after MAX_RETRIES = 8 # span typical overload windows; backoff grows per attempt
Defensive patterns
Strategy: retry
Try / catch
try:
response = call_api_with_retries()
except RuntimeError as e:
if "Max retries" in str(e):
schedule_retry_later(cooldown_minutes=10) # coarse outer retry
return "API overloaded; queued retry"
raise Prevention
- Set MAX_RETRIES and backoff to span realistic overload windows.
- Configure a FALLBACK_MODEL on a different provider.
- Throttle concurrent agent sessions during peak hours.
- Treat this as transient: queue and retry later, don't drop tasks.
When it happens
Trigger: Anthropic/API provider returning HTTP 529 or 'overloaded_error' for every attempt in the window; MAX_RETRIES set low while an incident is ongoing; a fallback model also overloaded (switching to FALLBACK_MODEL after MAX_CONSECUTIVE_529 doesn't help if it is saturated too); retry_delay backoff shorter than the incident.
Common situations: Provider capacity incidents at peak hours; small MAX_RETRIES/MAX_CONSECUTIVE_529 defaults in stress tests; bursty fan-out workloads from many agents sharing one key.
Related errors
- agent({{schema}}) invalid output: {err}
- workflow name must be a string
- workflow args must be an object
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/f7b38440256fec86.
Report an issue: GitHub.