[Feature] OnApiRetry hook event for observability and control over internal retry behavior

Resolved 💬 2 comments Opened Apr 12, 2026 by mjmirza Closed Jun 12, 2026

Summary

Claude Code retries API calls internally on 429, 529, and transient network errors. These retries are invisible to the user and to hooks. We propose a new OnApiRetry hook event that fires on each retry attempt, giving users and tooling a way to observe, log, and optionally intercept the retry loop.

Problem

Internal retries are a significant part of what the CLI does, but the current observability gap hurts users in several documented ways:

  1. Session unrecoverability from silent retry accumulation

#40316 documents sessions becoming permanently unrecoverable because retries silently accumulate. A hook to observe each retry would let users detect the runaway and bail before the session is lost.

  1. Retries eating rate limit budget invisibly

#44850 "Telemetry events competing with API requests for rate limit budget" shows users already suspect their budget is being consumed by internal traffic they cannot see. Retry visibility would settle this.

  1. Connection errors dropped with zero recovery

#37077 reports ECONNRESET, EPIPE, ETIMEDOUT errors fail immediately with no retry or visibility. A hook would let users implement their own policy (custom backoff, notification, switch to a different provider).

  1. 529 retry behavior inconsistent across modes

#35801 requests auto-retry on 529 in interactive mode. An OnApiRetry hook would let users implement this themselves while Anthropic decides on the default.

Proposed design

New hook event OnApiRetry fires just before each retry attempt. Input schema:

{
  "attempt": 2,
  "max_attempts": 5,
  "error_code": "429",
  "error_message": "rate_limit_exceeded",
  "retry_after_ms": 13000,
  "request_type": "messages",
  "session_id": "..."
}

Output contract mirrors the PermissionDenied pattern established in #37769:

{
  "action": "continue" | "abort" | "wait_longer",
  "systemMessage": "optional message to inject into conversation",
  "wait_ms": 30000
}

Users register it in settings.json like any other hook event.

Why existing issues do not cover this

Verified across 8 keyword searches (OnRetry hook, retry event, retry visibility, retry hook, retry observability, api retry callback, silent retry 429, 429 retry hook). Zero hits on a hook event fired on API-level retries.

Adjacent but distinct:

  • #45309 Hook Retry Limit. About retrying hooks themselves, not API calls. Opposite direction.
  • #37769 PermissionDenied hook event. Different lifecycle event (permission denial). Proves the appetite for new hook events and establishes the systemMessage output contract this proposal reuses.
  • #21531 BeforeModel and AfterModel hooks. Broader model hooks proposal. Our ask is narrower, scoped specifically to the retry path inside the request cycle.
  • #40872 Auto-retry last message after usage quota window resets. About retry behavior, not observability.

Use cases this unlocks

  • Statusline retry indicator. Show [retry 2/5 after 429] in the statusline.
  • Retry log file. Log every retry to ~/.claude/logs/retries.jsonl for cost attribution and post-mortem.
  • Opt out of silent retries. Return {action: abort} to fail fast on the first 429.
  • Custom backoff. Override wait_ms to implement exponential backoff tuned to the user's workload.
  • Provider failover. On N retries, write a signal file that a wrapper script watches for and switches providers.
  • Telemetry budget protection. Pause non-essential retries during high-usage windows, addressing #44850.

Request

  1. Implement OnApiRetry as a new hook event.
  2. Define input and output schemas in the hooks documentation.
  3. Fire the event on 429, 529, ECONNRESET, EPIPE, ETIMEDOUT, and other retryable error classes.
  4. Allow the hook to abort, continue, or modify the retry delay.

Suggested labels: feature request, area:hooks, area:api

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗