fix(infra): add NaN guard for unparseable timestamp in cost usage#99420
Conversation
…sage new Date(parsed.timestamp).getTime() can return NaN for unparseable strings. Without a guard, NaN silently propagates into downstream usage/cost calculations and corrupts billing data. Add Number.isNaN(timestamp) check, falling back to 0 (same default as the path when no timestamp key is present). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 4:00 AM ET / 08:00 UTC. Summary PR surface: Source +3. Total +3 across 1 file. Reproducibility: yes. at source level: current main assigns Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land one canonical linked PR that keeps Do we have a high-confidence way to reproduce the issue? Yes at source level: current main assigns Is this the best way to solve the issue? Yes; guarding the string parse in AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 7cb41ccc63f5. Label changesLabel justifications:
Evidence reviewedPR surface: Source +3. Total +3 across 1 file. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…sage (openclaw#99420) new Date(parsed.timestamp).getTime() can return NaN for unparseable strings. Without a guard, NaN silently propagates into downstream usage/cost calculations and corrupts billing data. Add Number.isNaN(timestamp) check, falling back to 0 (same default as the path when no timestamp key is present). Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…sage (openclaw#99420) new Date(parsed.timestamp).getTime() can return NaN for unparseable strings. Without a guard, NaN silently propagates into downstream usage/cost calculations and corrupts billing data. Add Number.isNaN(timestamp) check, falling back to 0 (same default as the path when no timestamp key is present). Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
What Problem This Solves
new Date(parsed.timestamp).getTime()insession-cost-usage.tscan returnNaNwhen the timestamp string is unparseable (e.g. "not-a-date", empty string, malformed). Without a guard, NaN silently propagates into downstream usage/cost calculations, corrupting billing data.Evidence
Real behavior proof (before vs after NaN guard)
Without the guard, the 4 non-date inputs produce
NaNwhich corrupts downstream calculations. With the guard, they safely fall back to 0 (the same default as when no timestamp key is present).Existing tests
57 of 58 session-cost-usage tests pass (the 1 failure is a pre-existing DST/Intl stub issue unrelated to this change).
Build verification
Full project builds successfully with the change.
Why This Change Was Made
This is a "present-but-invalid" boundary case — the timestamp key exists as a string, so we enter the
typeof parsed.timestamp === "string"branch, but the parsed value is garbage. The same guard pattern already exists elsewhere in the codebase. The fix is a 3-line addition with no change to any other code path.Merge Risk
Zero. The guard only activates when
new Date(...).getTime()returnsNaN, which was previously unhandled and would propagate corrupt data. All valid timestamps pass through unchanged.Fixes #99413
🤖 Generated with Claude Code