trace: the cursor readers crash on a JSON line that is not an object
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Newbie friendliness
- 25/100
Research direction
Start with the spool loop and cursor_events_to_claude in tokeneconomizer/trace/cursor.py, then compare their JSON handling with the existing guarded transcript loop. The issue describes the regression cases and says a regression test is ready; done means both readers skip valid JSON values that are not objects and preserve the other records. A linked pull request, #181, is already open.
Written by the indexing model from the issue text.
Description
What happens
cursor_events_to_claude and cursor_prompt_count (tokeneconomizer/trace/cursor.py) parse each line with json.loads and then call .get on the result, without the isinstance(ev, dict) check. A line that is valid JSON but not an object (null, 42, "text", [1, 2]) has no .get, so both readers raise AttributeError and one such line discards the whole session's trace.
#150 added that check to the 13 readers that missed it. cursor.py's two were not in that sweep — they came with the #149 headless work (the recorded-event spool and the agent_transcript fallback). The opencode, Claude, Codex and Copilot readers all have the check.
Repro
events.jsonl:
null
[1, 2]
{"hook_event_name": "UserPromptSubmit", "prompt": "hi"}
"str"
{"hook_event_name": "PostToolUse", "tool_use_id": "t1", "tool_name": "Shell", "tool_input": {"command": "pytest"}, "tool_response": {"content": "3 passed", "exit_code": 0}}
>>> from tokeneconomizer import trace
>>> trace.cursor_prompt_count("events.jsonl")
AttributeError: 'NoneType' object has no attribute 'get'
>>> trace.cursor_events_to_claude("events.jsonl", "out.jsonl")
AttributeError: 'NoneType' object has no attribute 'get'
Both lose every record in the file, not just the bad line. The prompt-count fallback loop over Cursor's own transcript (second loop) already has the isinstance(row, dict) guard; it is the spool loop and cursor_events_to_claude that miss it.
Impact
Cursor.prompt_count and the mechanism trace conversion abort mid-session. In a hook the fail-open rule turns the exception into {} plus an errors.log line, and the fold keeps the session pending and retries the same crash at the next session start — the same failure shape #150 fixed for the other readers.
Fix
The same one-line guard after json.loads in both places. I have it with a regression test ready and will open the PR.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 344
- Avg merge
- 17h 41m
- Merged PRs (30d)
- 73
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
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.
More from microsoft/TokenEconomizer
-
trace: Pi's 1-hour cache writes are priced at 1.25x, but billed at 2xPossibly taken @Shizoqua claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
microsoft/TokenEconomizer#221 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 15/100
microsoft/TokenEconomizer#219 ·
Maintainers usually reply within 1 day
-
CommandCode supportOpen
Difficulty 5/5 Over a week Newbie friendliness 25/100
microsoft/TokenEconomizer#205 ·
Maintainers usually reply within 1 day
-
Copilot CLI hooks fail on Windows: command runs under PowerShell, which can't execute te-hookPossibly taken @sykuang claimed this 3 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 72/100
microsoft/TokenEconomizer#204 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
microsoft/TokenEconomizer#193 ·
Maintainers usually reply within 1 day
All issues in microsoft/TokenEconomizer
Similar issues
-
documentation type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
add entry to blockOpen
Difficulty 1/5 Under an hour Newbie friendliness 65/100
StevenBlack/hosts#3299 ·
-
`garak --report` overwrites the input report when its name has no ".report"Possibly taken @0z5a claimed this today. Openneeds-triage
Difficulty 2/5 Half a day Newbie friendliness 72/100
Maintainers usually reply within 2 days
-
plot_graph crashes when a mesh node has no m2m edgePossibly taken @tygvi claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
mllam/neural-lam#883 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
microsoft/graphrag#2626 · 1 comment ·
Maintainers usually reply within 5 days