rtk gain panics with 'attempt to add with overflow' when any command has negative saved_tokens
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 81.1k
- Forks
- 5.1k
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 35
Description
Summary
A single tracked command whose RTK output is larger than its input makes rtk gain panic — permanently, for every later invocation, until the row is deleted by hand.
saved_tokens is stored as a signed integer and can legitimately be negative (RTK produced more output than the raw command). gain.rs reads it back as usize, so -51 becomes 18446744073709551565, and the running total overflows on the next add.
Reproduction
Any row with saved_tokens < 0 triggers it. On my machine four such rows arrived from a normal test run:
$ sqlite3 ~/.local/share/rtk/history.db \
"select original_cmd, input_tokens, output_tokens, saved_tokens
from commands where saved_tokens < 0;"
git worktree list|0|51|-51
find . -name '*.txt'|3|25|-22
find . -name 'cargo.toml'|3|25|-22
find . -name secret.txt|0|22|-22
$ rtk gain
thread 'main' (221433) panicked at src/core/tracking.rs:851:13:
attempt to add with overflow
rtk gain --history fails the same way. Deleting the negative rows restores both.
Cause
src/core/tracking.rs:841 casts the column straight to usize:
row.get::<_, i64>(3)? as u64, // exec_time_ms
row.get::<_, i64>(1)? as usize, // input
row.get::<_, i64>(2)? as usize, // output
row.get::<_, i64>(3)? as usize, // saved <- negative wraps here
then src/core/tracking.rs:851:
total_saved += saved; // overflow in debug, silently absurd in release
In a release build there is no panic — the totals and the savings percentage are simply nonsense, which is arguably worse.
Notes
git worktree listshowsinput_tokens = 0, output_tokens = 51, i.e. the raw command produced nothing and RTK's version produced 51 tokens. Whatever the merits of that, the analytics must survive it.- The "never worse" guard does not prevent these rows from being recorded.
- Distinct from the UTF-8 char-boundary panics (#3232, #3733, #2318, #2954, #2787) — this one is an integer overflow and does not depend on the command text.
- Distinct from #3853 ("No tracking data yet"), which is an empty database rather than a crash.
Suggested fix
Read the column as i64 and accumulate in i64, so negative savings subtract as they should, then clamp only at the presentation layer (a negative total is real information — it means RTK cost tokens over that window). A saturating cast would hide the signal.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at src/core/tracking.rs lines 841 and 851, where saved_tokens is read and added to the running total. Reproduce the issue with the negative saved_tokens rows shown in the report, then check both rtk gain and rtk gain --history. Done means negative savings no longer cause overflow or panic and the reported totals remain meaningful.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, sqlite
- Domain
- cli, databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100