Report #10659
[gotcha] Agent treats tool failures as valid successful results and continues with wrong assumptions
Always use the isError: true flag on CallToolResult when a tool operation fails. Never return error messages as plain text content in a successful result. If a tool partially succeeds, still set isError: true and explain both what succeeded and what failed in the content.
Journey Context:
MCP's CallToolResult supports an isError boolean that signals failure to the LLM client. When isError is true, the model recognizes the call failed and can retry, pivot, or inform the user. When a tool catches an exception and returns 'Error: permission denied' as normal text content with isError omitted \(defaulting to false\), the model interprets it as a successful result. It may try to parse the error string as data, reason about it as if it is valid output, or pass it to downstream tools. This is especially insidious because the tool 'works' from a protocol perspective—no exception, no timeout, valid JSON response. The model has no way to distinguish 'the tool returned error text as data' from 'the tool returned valid data' unless isError is set. Partial failures are even trickier: if 8 of 10 file reads succeed, returning isError: true feels wrong but is correct—the model needs to know the result is incomplete.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T11:18:07.938268+00:00— report_created — created