Summary
The sessions.usage API method computes aggregate totals (cost, tokens, messages) only from the sessions included after the limit parameter is applied. The default limit is 50. With more than 50 active session files, the aggregate totals silently exclude sessions beyond the top 50 by mtime.
Reproduction
# Default limit=50
openclaw gateway call sessions.usage --params '{"startDate": "2026-05-01", "endDate": "2026-05-01", "mode": "gateway"}' --json
# Returns: totalCost=$159.85
# limit=75
openclaw gateway call sessions.usage --params '{"startDate": "2026-05-01", "endDate": "2026-05-01", "mode": "gateway", "limit": 75}' --json
# Returns: totalCost=$331.24
Same date, same data — doubling the cost just by raising the limit from 50 to 75.
Root Cause
In src/gateway/server-methods/usage.ts, line ~549:
const limitedEntries = mergedEntries.slice(0, limit);
The aggregation loop then runs only over limitedEntries, not the full mergedEntries list. This means the aggregates (totals, daily breakdown, by-model, by-agent, by-channel) all reflect only the limited subset.
Expected Behavior
The limit parameter should control how many per-session detail entries are returned in the sessions array, but the aggregate totals (totals, aggregates.daily, aggregates.modelDaily, etc.) should be computed from all discovered sessions.
Impact
- Daily usage reports under-count by 15-60%+ depending on session count
- Historical queries (7-day trend) decay rapidly as newer sessions push older ones below the limit
- Cost tracking is unreliable for any setup generating >50 session files per day (common with subagents, thread sessions, and crons)
Environment
- ~140 active session files, ~280 archived (.deleted/.reset)
- Heavy subagent/thread/cron usage generating many short-lived sessions
Summary
The
sessions.usageAPI method computes aggregate totals (cost, tokens, messages) only from the sessions included after thelimitparameter is applied. The default limit is 50. With more than 50 active session files, the aggregate totals silently exclude sessions beyond the top 50 by mtime.Reproduction
Same date, same data — doubling the cost just by raising the limit from 50 to 75.
Root Cause
In
src/gateway/server-methods/usage.ts, line ~549:The aggregation loop then runs only over
limitedEntries, not the fullmergedEntrieslist. This means the aggregates (totals, daily breakdown, by-model, by-agent, by-channel) all reflect only the limited subset.Expected Behavior
The
limitparameter should control how many per-session detail entries are returned in thesessionsarray, but the aggregate totals (totals,aggregates.daily,aggregates.modelDaily, etc.) should be computed from all discovered sessions.Impact
Environment