# Missing terminal tool\_call when custom tool throws

**URL:** <https://forum.cursor.com/t/missing-terminal-tool-call-when-custom-tool-throws/168072>\
**Category:** Bug Reports\
**Tags:** mcp, cursor-sdk\
**Created:** [August 12, 2026, 12:18am UTC](https://forum.cursor.com/t/missing-terminal-tool-call-when-custom-tool-throws/168072 "2026-08-12T00:18:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_M](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/james_m/32/86150_2.png) [@James\_M](https://forum.cursor.com/u/James_M)\
**Post date:** [August 12, 2026, 12:18am UTC](https://forum.cursor.com/t/missing-terminal-tool-call-when-custom-tool-throws/168072/1 "2026-08-12T00:18:58Z")

</div>

### Where does the bug appear (feature/product)?

Cursor SDK

### Describe the Bug

When a custom MCP tool throws or otherwise never returns, the SDK does not emit a terminal tool\_call event. The transcript only persists tool calls on completed or error, so a running call whose tool never finishes is never written. I lose failed delegations entirely from the durable record.

### Steps to Reproduce

Run a conversation where custom tools (e.g. delegate) throw or hang without returning. Inspect the persisted transcript. In pr-delivery-loop I see 33 tool calls, all completed, with zero record of four delegations that failed. The only trace is model prose, not structured events.

### Expected Behavior

Every started tool\_call gets a terminal completed or error event in the transcript, even when the tool throws or the turn is cancelled.

### Version Information

issue-tracker app embedding @cursor/sdk on linux 6.12.67-linuxkit, Node in Cursor agent session, model composer.

---

<div class="post-metadata">

**Author:** ![deanrie](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/deanrie/32/1263_2.png) [@deanrie](https://forum.cursor.com/u/deanrie)\
**Post date:** [August 12, 2026, 6:00am UTC](https://forum.cursor.com/t/missing-terminal-tool-call-when-custom-tool-throws/168072/5 "2026-08-12T06:00:08Z")

</div>

Hey, thanks for the detailed report. The breakdown is, as always, top-notch.

Confirmed, what you described is reproducible. In the local SDK runtime, the terminal `tool_call` event really doesn’t make it into the transcript when a custom/MCP tool throws an exception or hangs, and finished calls get stamped as `completed` with no way to get `status: "error"`. So `33 tool calls, all completed` with four failed delegations is exactly the behavior we’re seeing.

I’ve passed this to the team. I can’t share an ETA yet, but I’ll reply in this thread when there’s an update.

If you have a minimal repro script (a custom tool that throws + a snippet that reads `run.messages()`), please attach it. It’s not required to reproduce, but it’d still be helpful.

---

<div class="post-metadata">

**Author:** ![deanrie](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/deanrie/32/1263_2.png) [@deanrie](https://forum.cursor.com/u/deanrie)\
**Post date:** [October 7, 2026, 8:25am UTC](https://forum.cursor.com/t/missing-terminal-tool-call-when-custom-tool-throws/168072/8 "2026-10-07T08:25:05Z")

</div>

Hey @James_M,

Thanks again for the detailed report. There is already a way to save failed calls in the durable transcript: instead of letting a custom tool throw an exception, catch the error inside `execute` and return it as a result with `isError: true`, for example:

```ts
return { content: [{ type: "text", text: err.message }], isError: true };

```

That result goes through the normal completion path, so the call gets a terminal `tool_call` event with its `args` and error payload. The status will still be `completed`, but you can use `result.isError` to tell failed calls from successful ones.

For tools that may hang, wrap the work in your own timeout, for example `Promise.race` against a timer, and return an `isError` result when it fires. You’ll get the same kind of terminal record.

If calls still disappear from `run.messages()` on the latest SDK, write back here with details and we’ll take a closer look.
