Skip to content

Grok token totals never reach Usage & Spend: x.ai/billing returns -32601 on grok CLI 1.0.25 and the local session summary is dropped #3716

Closed

Description

@Chipagosfinest

Summary

Grok token totals never reach Usage & Spend or the shareable usage card, even with a fully populated local session history. On this machine ~/.grok/sessions/**/signals.json holds 88 sessions inside the 30-day window totalling ~18.3M tokens by GrokLocalSessionScanner's own formula, and the emitted snapshot contains no costUsage key at all — so grokLocalTokenSnapshot returns nil, Grok is placed in confirmedEmptySourceIDs, and it is absent from the spend dashboard and from every shared card.

Environment

  • CodexBar 0.60.3 (146), Homebrew cask, macOS 26
  • grok CLI 1.0.25 at ~/.npm-global/bin/grok
  • Grok enabled in ~/.config/codexbar/config.json; tokenCostUsageEnabled = 1

Observed

codexbar usage --provider grok --json returns only identity plus a quota percentage — no token fields:

{ "source": "grok-cli-proxy", "provider": "grok", "version": "1.0.25",
  "usage": { "primary": { "usedPercent": 100, "resetsAt": "2026-09-18T17:06:33Z" },
             "secondary": null, "tertiary": null, "loginMethod": "X Premium+" } }

--log-level debug shows the RPC billing method is gone from this CLI version:

grok rpc -> {"jsonrpc":"2.0","id":2,"params":{},"method":"x.ai/billing"}
grok rpc <- {"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"Method not found"}}
Grok RPC stopping
== Grok 1.0.25 (grok-cli-proxy) ==

So x.ai/billing returns -32601 Method not found on grok 1.0.25, the probe falls back to a quota-only snapshot, and the local session tokens are not attached to it.

Local data that should have been surfaced

files matched ~/.grok/sessions/*/*/signals.json : 88
files with mtime inside 30 days                 : 88
files with non-zero tokens                      : 88
sum of (totalTokensBeforeCompaction + contextTokensUsed) : > 18,339,779

Those are exactly the two fields GrokLocalSessionScanner reads (GrokLocalSessionScanner.swift:123-126), and every file carries primaryModelId, so models would populate too.

Where it goes wrong

GrokStatusProbe.toUsageSnapshot() (GrokStatusProbe.swift:69) sets costUsage: self.localSummary?.toCostUsageTokenSnapshot(...), so a nil localSummary silently yields a snapshot with no token history. Both strategies appear to intend to supply it — GrokWebFetchStrategy passes localSummary: self.localSummary(context.env) (GrokProviderDescriptor.swift:427, :454) and GrokStatusProbe.fetch computes it at :139 — yet the snapshot produced on the grok-cli-proxy path (GrokProviderDescriptor.swift:311, :313, :491) arrives without it. I could not pin the exact line by reading alone and did not want to guess; the observable contract is that a -32601 billing failure returns a snapshot whose costUsage is nil despite a populated local summary being available.

Downstream consequences, for completeness:

  • UsageStore+TokenCost.swift:517 → grokLocalTokenSnapshot returns nil
  • SpendDashboardController.swift:295-308 → Grok added to confirmedEmptySourceIDs, continue
  • ShareStatsPayload.swift:258 → no Grok provider row, so nothing to share

Suggested direction

Treat a missing/renamed RPC billing method as "quota unavailable" rather than "no usage data": keep returning the local GrokLocalSessionSummary on that path so token totals survive even when x.ai/billing is absent. Separately, x.ai/billing disappearing in grok 1.0.25 may warrant a version probe or a fallback method name.

Also worth noting for expectations: Grok can never contribute a per-model breakdown, since toCostUsageTokenSnapshot hardcodes modelBreakdowns: nil (GrokLocalSessionScanner.swift:58) while the card's model list is built from modelBreakdowns. Token totals are achievable; per-model rows are not, by construction.

Activity

  1. added
    P2Normal priority bug or improvement with limited blast radius.
    impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.
    issue-rating: 🦪 silver shellfishThin issue quality; more reproduction proof or environment detail is needed.
    on Sep 17, 2026
  2. clawsweeper commented on Sep 17, 2026

    @clawsweeper

    Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve. Reviewed September 17, 2026, 3:59 PM ET / 19:59 UTC.

    Summary
    Keep open for the reported dashboard omission, but the proposed cause is not established: CLI JSON deliberately excludes live token history, and the successful proxy path already attaches local sessions. Existing Grok history PRs overlap the investigation; repository policy also prohibits automatic closure.

    Reproducibility: no. the supplied CLI output cannot demonstrate missing live token history because serialization excludes it. The reported dashboard omission has not been reproduced; this read-only review ran no tests or provider probes.

    Next step
    Establish the app-side empty scan or publication boundary on a current build, with redacted counts and dashboard state; coordinate with the open Grok history work before creating another repair branch.

    Review details

    Best possible solution:

    Keep local token publication independent of quota availability while preserving account isolation, the live-only serialization contract, and truthful token-only reporting.

    Do we have a high-confidence way to reproduce the issue?

    No: the supplied CLI output cannot demonstrate missing live token history because serialization excludes it. The reported dashboard omission has not been reproduced; this read-only review ran no tests or provider probes.

    Is this the best way to solve the issue?

    Unclear: the proxy path already supplies local history, so adding another billing fallback is not yet justified. First identify where the app’s scan or publication becomes empty, using the existing account-isolation tests as a constraint.

    AGENTS.md: found and applied where relevant.

    Remaining risk / open question:

    • The actual app-side scan result, resolved Grok directory, selected dashboard window, and publication state were not captured, so the dashboard omission remains unverified.
    • Reusing an older token publication indiscriminately could defeat the existing account-isolation behavior.

    Codex review notes: model internal, reasoning medium; reviewed against b6e65a83dc47.

    Label changes

    Label changes:

    • add P2: The reported omission affects one provider’s usage reporting without blocking the app or provider access.
    • add impact:other: The issue concerns missing token totals in analytics and shared cards, with no evidence that underlying session files were lost.
    • add issue-rating: 🦪 silver shellfish: Current issue advisory state selects this label.

    Label justifications:

    • P2: The reported omission affects one provider’s usage reporting without blocking the app or provider access.
    • impact:other: The issue concerns missing token totals in analytics and shared cards, with no evidence that underlying session files were lost.
    Evidence reviewed

    What I checked:

    • CLI JSON does not establish missing live tokens: UsageSnapshot excludes costUsage from CodingKeys and encode(to:); decoding explicitly resets it to nil as live-only history. ProviderPayload encodes this UsageSnapshot directly. Therefore the reported missing JSON key cannot establish that the app received a nil local summary. (Sources/CodexBarCore/UsageFetcher.swift:287, b6e65a83dc47)
    • Successful proxy fallback retains the local scan: The OAuth proxy strategy delegates to GrokWebFetchStrategy.fetch, whose successful result awaits localSummary(context.env) and passes it through GrokUsageSnapshot.toUsageSnapshot(). That mapper attaches daily local tokens independently of RPC billing. docs/grok.md already documents Method not found as an expected fallback condition. (Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift:454, b6e65a83dc47)
    • Dashboard omission requires a separate publication diagnosis: The dashboard marks Grok empty when its token projection returns nil. That projection deliberately refuses a previously published fallback when a nonnil provider snapshot lacks costUsage; the corresponding test describes account isolation. Full provider failure separately scans and publishes local tokens. These paths warrant tracing with the reported setup, rather than unconditionally reusing old account data. (Sources/CodexBar/Providers/Grok/UsageStore+GrokLocalSessions.swift:10, b6e65a83dc47)
    • Existing token-only contract and coverage: docs/grok.md states that daily local buckets feed Usage & Spend without converting quota credits into dollars. GrokLocalSessionScannerTests cover populated daily buckets, empty homes, and token projection without remote billing; GrokTokenSnapshotProjectionTests cover published-data reuse and account isolation. These tests were inspected, not executed. (Tests/CodexBarTests/GrokLocalSessionScannerTests.swift:95, b6e65a83dc47)
    • Merged feature history and routing: GitHub verifies Publish live Grok tokens and xAI spend into Usage & Spend #3085 merged the shared Grok token catalog and was authored by Chipagosfinest. GitHub also verifies steipete authored merged Keep Grok session scans off the menu thread #3198, moving scans off the menu thread. Local logs corroborate both commits. Exact historical source attribution could not be completed because a required historical blob was unavailable; no introduction claim is made. (Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift, 41d904fd6d88)
    • Release comparison does not establish a new fix: The inspected Grok scanner, provider strategy, and app projection have no diff between v0.60.4 and reviewed main; UsageFetcher also has no diff against v0.60.4. The Grok files likewise have no diff against reported v0.60.3. No later fix for this reported omission was established. (Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift:454, b6e65a83dc47)

    Likely related people:

    • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
    • Chipagosfinest: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
    How this review workflow works
    • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
    • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
    • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
    • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
    • Maintainers can also comment @clawsweeper review to request a fresh review only.
    • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
    • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
    • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
  3. steipete commented on Sep 21, 2026

    @steipete
    Owner

    I could not reproduce successful-proxy token loss on main 55c0d8d23822. A synthetic CLI returning -32601 Method not found, followed by proxy quota, preserves local signals.json tokens through costUsage, Usage & Spend, and the share payload. The CLI JSON encoder intentionally omits costUsage, even when present in memory, so that JSON alone does not establish the loss. This issue should remain open pending a sanitized session-layout/configuration reproducer or an in-memory fetch diagnostic. No dollar estimate or per-model token allocation was invented.

  4. steipete commented on Sep 24, 2026

    @steipete
    Owner

    Thanks @Chipagosfinest. The existing regression from #3805 passes on current code: a stub CLI returns -32601, proxy billing succeeds, and all 42 fixture tokens reach Usage & Spend and the share payload. costUsage is intentionally omitted from usage JSON, so its absence there does not establish an in-memory token drop. #3947 fixes a narrower issue: missing-method classification depended on English wording, which could bypass the team fallback and its local summary. Both new classification cases fail before the fix and pass afterward. The reported personal-account dashboard loss remains unverified; the signed 0.65.0 CLI timed out in this verification attempt. Keep this issue open pending affected-account evidence from the app or its published in-memory snapshot.

  5. added a commit that references this issue on Sep 28, 2026
    03f4b68
  6. mattsilv commented on Oct 9, 2026

    @mattsilv

    Still seeing this on CodexBar 0.73.0 with Grok Build CLI 1.0.50 (macOS 26.6, X Premium+ account with bundled SuperGrok, freshly logged in with grok login). Unlike the regression test here, the proxy billing step does not succeed for me:

    • Source cli: Grok request failed: Method not found (-32601 on x.ai/billing).
    • Source oauth: Grok web billing RPC failed with status 1: Timeout expired, also with --web-timeout 60. Debug log shows only errorCategory=network provider=grok sources=grok.oauth (oauth): failed: network.

    So no quota is shown at all. I haven't tried the cookie source. Happy to run a debug build or share more logs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦪 silver shellfishThin issue quality; more reproduction proof or environment detail is needed.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions