trace: the cursor readers crash on a JSON line that is not an object

Aperta
#180 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@rahul05ranjan ci sta già lavorando.

Dal 9/11/2026.

  • #181 di @rahul05ranjan — aperta

Valutazione

Difficoltà
1/5
Tempo stimato
Meno di un'ora
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
python
Ambito
backend

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.

Lingua principale
Python
Stelle
5.6k
Fork
344
Merge medio
14h 41m
PR unite (30g)
54

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/TokenEconomizer

Tutte le issue di microsoft/TokenEconomizer

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.