[FEATURE] Pass quotaLimits (rateLimitType, resetsAt) to the StopFailure hook input
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
A StopFailure hook can't tell which usage limit ended the turn.
On 2.1.284 the StopFailure input is the base fields plus error, error_details? and last_assistant_message?. For a usage-limit 429, error is "rate_limit" whatever the limit is (five_hour, seven_day, seven_day_opus, seven_day_sonnet, seven_day_overage_included, overage). The kind appears only in the display text of last_assistant_message ("You've hit your session limit · resets 12am (Asia/Tokyo)", "weekly limit", "Opus limit", ...). So a hook has to match English UI copy, and gets the reset time only as a localized clock string.
The structured values already exist. The synthetic assistant message that Claude Code writes to the transcript for that 429 carries quotaLimits, for example (2.1.280, abridged; the other fields are overage and upgrade state):
"error": "rate_limit",
"quotaLimits": {
"status": "rejected",
"rateLimitType": "five_hour",
"resetsAt": 1790175600,
"lowPriorityRetryAfterSeconds": 20
}
They just aren't copied into the hook input.
Related: #94811 asks for a coarse error_class and retry_after_seconds on StopFailure. This request is narrower: pass through the quota fields Claude Code already has.
Proposed Solution
When the failing message has quotaLimits, add to the StopFailure input:
rate_limit_type:quotaLimits.rateLimitTyperesets_at:quotaLimits.resetsAt(epoch seconds)
Both are absent when the stop was not a usage limit, so existing hooks are unaffected.
Alternative Solutions
- Match the text of
last_assistant_message. It breaks when the wording or locale changes, and new per-model limits need new patterns. - Read
transcript_pathand find the lastisApiErrorMessageline. This means parsing the transcript JSONL from inside a hook, for two values Claude Code already has in memory.
Priority
Low - Nice to have
Feature Category
Developer tools/SDK
Use Case Example
A status display driven by hooks shows why a session stopped and what to do, because the right response differs by limit:
| rateLimitType | What the user does |
|---|---|
| five_hour | wait until resetsAt |
| seven_day | stop for the week |
| seven_day_opus / seven_day_sonnet / seven_day_overage_included | switch models (the message itself says so) |
With rate_limit_type and resets_at in the hook input, the display can show "session limit, resets 00:00" or "Opus limit, switch models" without parsing UI text.
Additional Context
- Claude Code 2.1.284, Windows 11, CLI.
- On this machine the main-session transcripts hold 20 usage-limit messages with
quotaLimits(2.1.267 to 2.1.280), allfive_hour. In all 20,resetsAtmatched the reset time in the message text.