Skip to content

fix(api): tolerate null resets_at for unused usage windows#18

Open
jeanfw wants to merge 1 commit into
eddmann:mainfrom
jeanfw:fix/null-resets-at
Open

fix(api): tolerate null resets_at for unused usage windows#18
jeanfw wants to merge 1 commit into
eddmann:mainfrom
jeanfw:fix/null-resets-at

Conversation

@jeanfw
Copy link
Copy Markdown

@jeanfw jeanfw commented May 10, 2026

Summary

The Claude API legitimately returns resets_at: null on usage windows that have no consumption yet — typically when an account hasn't been used in the last 5 hours (so there's no active session window to reset). Today the mapper rejects these responses and surfaces:

Server response missing critical field: fiveHour.resetsAt

…which blocks refresh entirely for that account. The popover shows the orange Server returned invalid response banner and the user has no recourse short of using Claude on that account to force the API to populate the field again.

The fix

UsageAPIResponse.toDomain() now treats a null resets_at the same way it already treats a null sevenDaySonnet.resets_at: it falls back to now + window duration (5 hours for the session window, 7 days for the weekly window). A present-but-malformed date string is still treated as a hard error, since that's a real protocol violation.

Logic is factored into a small parseResetDate(from:field:formatter:fallback:) helper so all three windows use the same path.

Test plan

  • test_usageFetch_withMissingResetAt_fillsInFallbackWindow covers the new behaviour — null resets_at on the session window decodes to a future date roughly one session-window from now.
  • test_usageFetch_withMalformedResetAt_surfacesInvalidResponse ensures the strict path is still wired up — a non-ISO string surfaces AppError.networkError(.invalidResponse).
  • All existing tests still pass (the previous test_usageFetch_withInvalidPayload_surfacesInvalidResponse was renamed to make the intent unambiguous after this change).

🤖 Generated with Claude Code

The Claude API legitimately returns 'resets_at: null' for usage windows
with no consumption yet (e.g. a client account that hasn't been used
today). The mapper was rejecting these responses, surfacing 'Server
response missing critical field: fiveHour.resetsAt' in the popover and
blocking refresh entirely. Now a null reset_at falls back to now plus
the window duration (matching the existing behaviour for sonnet usage).
A present-but-malformed date string is still treated as a hard error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant