# `tool_call:completed` event lost after connection reconnect in `stream-json` mode
**Category**: Support / Bug Reports
**Tags**: cli
## Where does the bug appear (feature/product)?
Cursor CLI (`agent` command with `–output-format stream-json --stream-partial-output`)
## Describe the Bug
When using `–output-format stream-json --stream-partial-output`, if a connection drop occurs (emitting `connection:reconnecting` → `retry:starting` → `retry:resuming` → `connection:reconnected`) while a `tool_call:started` event has already been emitted but its corresponding `tool_call:completed` has not, **the `completed` event is permanently lost** after reconnect.
The CLI resumes from a checkpoint and continues with new `thinking`/`assistant`/`tool_call` events, but never emits the missing `completed` event for the interrupted tool call.
### Observed NDJSON sequence (from real production trace):
```jsonl
// Line 215: tool_call started — read a file
{“type”:“tool_call”,“subtype”:“started”,“call_id”:“tool_5189c71e-ea33-48cf-86d3-a2a3b29422b”,“tool_call”:{“readToolCall”:{“args”:{“path”:“/worker/exec/2/.cursor/skills/run-data-query/scripts/run_data_tools.py”,“offset”:1,“limit”:50}}},“session_id”:“…”,“timestamp_ms”:1776080394435}
// Line 216-219: connection drops and reconnects (~33s later, reconnect takes ~24s)
{“type”:“connection”,“subtype”:“reconnecting”,“session_id”:“…”,“timestamp_ms”:1776080427217}
{“type”:“retry”,“subtype”:“starting”,“session_id”:“…”,“timestamp_ms”:1776080429370,“attempt”:1,“is_resume”:true}
{“type”:“retry”,“subtype”:“resuming”,“session_id”:“…”,“timestamp_ms”:1776080429370,“checkpoint_turn_count”:1,“attempt”:1}
{“type”:“connection”,“subtype”:“reconnected”,“session_id”:“…”,“timestamp_ms”:1776080450937}
// Line 220+: resumes with NEW thinking events — NO tool_call:completed for call_id tool_5189c71e-…
{“type”:“thinking”,“subtype”:“delta”,“text”:“…”,“session_id”:“…”,“timestamp_ms”:1776080475313}
```
**The `tool_call:completed` for `call_id=tool_5189c71e-ea33-48cf-86d3-a2a3b29422b` is never emitted.**
### Impact on consumers
For consumers that track pending tool calls (matching `started` ↔ `completed` by `call_id`):
1. The orphaned `call_id` stays in the pending set forever
2. Any logic gated on “all pending tools completed” (e.g., step boundaries in a ReAct trace) is permanently broken
3. All subsequent tool calls get merged into a single oversized step instead of being properly segmented
In our case, a step that should have contained ~2 tool calls ended up with **11 tool calls** because the orphan prevented step completion.
### Additional issue: undocumented event types
The `connection` and `retry` event types (`reconnecting`, `reconnected`, `starting`, `resuming`) are not documented anywhere in the CLI stream-json specification. Consumers have no way to know these exist or how to handle them.
## Expected Behavior
One of:
1. **Preferred**: After reconnect, re-emit the missing `tool_call:completed` event (with the actual result, since the tool did execute server-side)
2. **Acceptable**: Emit a `tool_call:cancelled` or `tool_call:lost` event so consumers can clean up their pending state
3. **Minimum**: Document the `connection`/`retry` event types and recommend that consumers treat `connection:reconnecting` as an implicit cancellation of all pending `tool_call:started` events
## Steps to Reproduce
1. Run a long Cursor CLI task with `–output-format stream-json --stream-partial-output` that makes many tool calls
2. During execution, cause a network interruption (or wait for a natural connection drop)
3. Observe that the CLI reconnects and resumes, but any in-flight `tool_call:started` events never receive their `completed` counterpart
## Environment
- Cursor CLI version: latest (April 2026)
- Flags: `–output-format stream-json --stream-partial-output --model composer-2`
- OS: Linux
## Related
This is a follow-up to my earlier post about undocumented assistant event forms: