[Bug]: Replayed Claude wake result counts a gateway's relative reset from replay time#25021
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Follow-up to #17778, which taught the Claude adapter to read the wrapped gateway 503 (reset after …) duration. That duration is counted from the wrong moment when the result is replayed from the wake buffer.
Filed by Claude Code (Claude Opus 5.5) at the user's request.
Area
apps/server
Steps to reproduce
- Route a Claude thread through a gateway that reports pool cooldowns with the wrapped 503, e.g. a CLIProxyAPI account pool:
API Error: 503 [...] [429]: {"type":"error","error":{"type":"rate_limit_error",...}} (reset after 2h54m21s). - Start a background task and let the root turn end.
- Let the task finish while every credential is cooling down. Claude Code opens the wake turn itself and the request fails. No T3 turn is active, so the adapter buffers the wake frames and requests a continuation run.
- The thread is limited, so the continuation run waits. Auto-resume later starts another turn first, and it succeeds.
- The queued continuation then starts and replays the buffered result.
The test anchors a replayed wake gateway limit to when its result arrived in the linked PR reproduces this: it buffers the result, advances the TestClock one hour, then starts the continuation.
Expected behavior
resetAt is the time the gateway result arrived plus the reported duration, the same value T3 computes when a turn is active.
Actual behavior
providerFailureFromResult adds the duration to DateTime.now at replay, so all the time the continuation spent queued is added to the reset. From the affected thread (UTC):
| Time | Event |
|---|---|
| 14:45:45 | Last wake result arrives while idle: reset after 2h54m21s, so the cooldown ends at 17:40:06 |
| 17:40:07 – 17:42:39 | Auto-resume runs a new turn, which succeeds |
| 17:42:44.9 | The queued continuation starts and replays the buffered result |
| 17:43:14 | The continuation fails with resetAt 20:37:05.908 (17:42:44.908 + 2h54m21s) |
T3 armed snooze and auto-resume for 20:37, about three hours after the cooldown ended. The thread sat idle until the user continued it by hand.
With the arrival time as the base, the reset is already past at replay, so T3 does not hold the thread. The stale failure is still recorded on that continuation run, which is a separate question.
Impact
Major degradation or frequent failure
Version or commit
T3 Code 0.1.2 where it happened; reproduced on main @ 3816296021 with the test above.
Environment
Ubuntu 20.04 server host, Claude Code 2.1.310, Claude Opus through a CLIProxyAPI account pool.
Logs or stack traces
| 1 | # provider event log: wake result received while no T3 turn was active |
| 2 | 2026-10-25T14:45:45.333Z incoming result origin=task-notification |
| 3 | API Error: 503 [cpa/claude-opus-5-5] [429]: {"type":"error","error":{"type":"rate_limit_error","message":"All credentials for model claude-opus-5-5 are cooling down (...)"}} (reset after 2h54m21s). |
| 4 | # continuation provider turn: started 17:42:44.907Z, completed 17:42:44.908Z |
| 5 | # error turn item and limit recovery on the thread |
| 6 | {"class":"usage_limit","code":"api_error_429","retryable":true,"resetAt":"2026-10-25T20:37:05.908Z"} |
| 7 | {"resetAt":"2026-10-25T20:37:05.908Z","autoResume":true,"snooze":true} |
Workaround
Send a message once the limit has actually cleared.