TanStack / TanStack/ai

Cancelled/denied tool calls are indistinguishable from genuine failures

Open
#1,386 0 comments 0 reactions 1 assignee View on GitHub

@tombeckenham is already working on this.

Since Sep 17, 2026.

has-pr waiting-on: maintainer
Dominant language
TypeScript
Stars
3.1k
Forks
331
Avg merge
1d 22h
Merged PRs (30d)
160

Description

TanStack AI version

@tanstack/ai v0.54.0 (also v0.53.0)

Framework/Library version

Framework-agnostic (plain Node.js)

Describe the bug and the steps to reproduce it

A cancelled or user-denied tool call is emitted with the same shape as a genuine failure, so a consumer can't tell them apart. Both produce state: 'output-error' + { error: <hardcoded string> } (packages/ai/src/activities/chat/tools/tool-calls.ts):

  • Cancel (:807-813): { error: 'Tool execution cancelled' }
  • Deny (:912-923, :1001-1009, via deniedApprovalResult :486-490): { error: 'User declined tool execution' }

That is identical to real failures — unknown tool (:787), arg-parse (:826), validation (:848). The only discriminator is the hardcoded English string; there's no distinct state, since ToolResultState is 'streaming' | 'complete' | 'error' (types.ts:76).

The framework does know the outcome structurally — the InterruptStore record's status is 'cancelled' — but that's discarded when the TOOL_CALL_RESULT is built, and only { error: <string> } survives into the persisted ModelMessage a UI re-hydrates from. So after reload, matching that localizable string is the only option left.

Runnable repro (no API key) + verified output are in the linked sandbox: an approval-deny and a genuine execute() throw come back byte-identical except for the error string.

Expected: a structured, persistable signal for "user cancelled/declined", distinct from a failure — a terminal state, a discriminator on the result, or (minimally) exported constants for the two strings. Ideally carry through the outcome the InterruptStore already records.

Your Minimal, Reproducible Example - (Sandbox Highly Recommended)

https://stackblitz.com/github/oztune/tanstack-ai-cancel-repro

Screenshots or Videos (Optional)

No response

Do you intend to try to help solve this bug with your own PR?

No response

Terms & Code of Conduct
  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.