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

Abierto
#180 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@rahul05ranjan ya está trabajando en esto.

Desde el 9/11/2026.

  • #181 de @rahul05ranjan — abierto

Evaluación

Dificultad
1/5
Tiempo estimado
Menos de una hora
Aptitud para principiantes
25/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Estancado
Stack tecnológico
python
Área
backend

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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.

Lenguaje dominante
Python
Estrellas
5.6k
Forks
344
Merge medio
14 h 41 min
PR fusionados (30 d)
54

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/TokenEconomizer

Todos los issues de microsoft/TokenEconomizer

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.