Skip to content

fix(core): preserve tool execution error state#17710

Open
littlewwwhite wants to merge 1 commit into
mastra-ai:mainfrom
littlewwwhite:codex/fix-tool-error-history-state
Open

fix(core): preserve tool execution error state#17710
littlewwwhite wants to merge 1 commit into
mastra-ai:mainfrom
littlewwwhite:codex/fix-tool-error-history-state

Conversation

@littlewwwhite

@littlewwwhite littlewwwhite commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Persist failed tool executions as output-error history parts instead of successful result parts.
  • Keep legacy AI SDK v4 and Mastra v1 conversion paths compatible by mapping stored tool errors back to legacy tool-result messages when needed.
  • Add regression coverage for persisted tool errors, v4 sanitization, v1 conversion, and the agent-network final result shape.

Fixes #15569.

Testing

  • pnpm --filter ./packages/core exec vitest run src/loop/workflows/agentic-execution/llm-mapping-step.test.ts
  • pnpm --filter ./packages/core exec vitest run src/agent/message-list/conversion/output-converter-provider-executed.test.ts
  • pnpm --filter ./packages/core exec vitest run src/agent/message-list/prompt/convert-to-mastra-v1.test.ts
  • pnpm --filter ./packages/core exec vitest run src/agent/agent-network.test.ts --testNamePattern "should NOT store redundant toolCalls"
  • pnpm --filter ./packages/core exec vitest run src/loop/loop.test.ts -u
  • pnpm --filter ./packages/core exec vitest run src/loop/loop.test.ts
  • pnpm --filter ./packages/core check
  • pnpm test:core
  • pnpm --filter ./packages/core lint
  • pnpm build:core
  • git diff --check

CodeRabbit CLI was not available locally (coderabbit and cr were not found).

ELI5

When a tool breaks and throws an error, the system now correctly saves that failure to the conversation history instead of marking it as a successful result. When the conversation is reloaded later, the error stays properly marked as an error—with all the error details preserved—instead of being confusingly converted to a successful output.

Summary

This PR fixes a data persistence issue where tool execution errors were incorrectly stored and loaded from conversation history. Previously, when a tool's execute() method threw an error, the error was persisted with state: "result" and the error text in the result field. Upon reloading from history, this appeared as a successful tool execution with the error message in the output, losing the semantic meaning that the tool had failed.

Changes Overview

Core Fix — llm-mapping-step.ts
Modified the tool error handling in createLLMMappingStep to persist failed tool executions with the correct state and error field. When a tool throws, it now calls messageList.updateToolInvocation with:

  • state: 'output-error' (instead of 'result')
  • errorText: reifiedError.message (instead of putting the error in a result field)

Compatibility Layer — output-converter.ts
Extended sanitizeAIV4UIMessages to handle output-error tool invocations when converting to legacy AI SDK v4 format. Introduced toAIV4CompatibleToolInvocation helper that maps output-error invocations back to state: 'result' with the errorText moved to the result field, ensuring backward compatibility. Also updated toolInvocations filtering to preserve both successful results and errors.

V1 Conversion — convert-to-mastra-v1.ts
Added two helper functions to support tool errors in Mastra v1 message format:

  • hasToolOutcome: Returns true for tool invocations with state: 'result' (with a result field) or state: 'output-error'
  • toToolResultPart: Maps both successful and error tool invocations to v1 tool-result messages, converting output-error by using errorText as the result content

These helpers ensure that both successful and failed tool executions are properly included in tool-result messages during v1 conversion.

Tests

  • Added regression test in llm-mapping-step.test.ts verifying that tool errors are persisted with state: 'output-error' and errorText
  • Added test in output-converter-provider-executed.test.ts validating v4 sanitization converts output-error to legacy result format
  • Added test in convert-to-mastra-v1.test.ts confirming v1 conversion handles output-error tool invocations
  • Updated test in agent-network.test.ts to accept both tool-result and tool-error entries in final results

Changeset
Added @mastra/core patch release note documenting that tool execution errors are now properly preserved in reloaded conversation history (closes #15569).

Persist failed tool executions as output-error history parts while keeping legacy message conversion compatible.\n\nFixes mastra-ai#15569.
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b87ba02

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@mastra/core Patch
mastracode Patch
@mastra/mcp-docs-server Patch
@internal/playground Patch
@mastra/client-js Patch
@mastra/opencode Patch
@mastra/longmemeval Patch
mastra Patch
@mastra/deployer-cloud Patch
@mastra/react Patch
@mastra/playground-ui Patch
@mastra/server Patch
@mastra/deployer Patch
create-mastra Patch
@mastra/express Patch
@mastra/fastify Patch
@mastra/hono Patch
@mastra/koa Patch
@mastra/nestjs Patch
@mastra/temporal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

@littlewwwhite is attempting to deploy a commit to the Mastra Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 93715143-2fa9-44fb-b69e-1f201ce1f132

📥 Commits

Reviewing files that changed from the base of the PR and between 36df947 and b87ba02.

⛔ Files ignored due to path filters (1)
  • packages/core/src/loop/__snapshots__/loop.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • .changeset/soft-bushes-crash.md
  • packages/core/src/agent/agent-network.test.ts
  • packages/core/src/agent/message-list/conversion/output-converter-provider-executed.test.ts
  • packages/core/src/agent/message-list/conversion/output-converter.ts
  • packages/core/src/agent/message-list/prompt/convert-to-mastra-v1.test.ts
  • packages/core/src/agent/message-list/prompt/convert-to-mastra-v1.ts
  • packages/core/src/loop/workflows/agentic-execution/llm-mapping-step.test.ts
  • packages/core/src/loop/workflows/agentic-execution/llm-mapping-step.ts

Walkthrough

Tool execution errors are now preserved correctly when conversation history is reloaded. Failed tool calls are stored as output-error state with errorText instead of state: 'result', and all message conversion paths support this state to ensure consistency across v1 and AIV4 UI formats.

Changes

Tool Execution Error Preservation

Layer / File(s) Summary
Tool error persistence in LLM mapping step
packages/core/src/loop/workflows/agentic-execution/llm-mapping-step.ts, llm-mapping-step.test.ts
Tool execution errors are recorded in message history with state: 'output-error' and errorText field instead of state: 'result'. New test validates error is persisted with correct state and error message.
Mastra v1 message conversion for output-error
packages/core/src/agent/message-list/prompt/convert-to-mastra-v1.ts, convert-to-mastra-v1.test.ts
Conversion to v1 format introduces hasToolOutcome and toToolResultPart helpers to handle both successful results and output-error states, converting errors to tool-result messages with error text in the result field across three usage sites.
AIV4 UI compatibility sanitization
packages/core/src/agent/message-list/conversion/output-converter.ts, output-converter-provider-executed.test.ts
AIV4 UI messages are sanitized to transform output-error tool invocations into legacy result-state structures by mapping errorText to the result field for backward compatibility.
Integration test validation
packages/core/src/agent/agent-network.test.ts
End-to-end test is updated to validate that tool outcomes include both tool-result and tool-error messages in final results.
Release documentation
.changeset/soft-bushes-crash.md
Patch release documents that tool execution errors are now handled so reloaded history preserves failed tool calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mastra-ai/mastra#17388: Extends tool-error persistence by storing output-error state and updating message conversions to handle the new state across the same conversion pathways.
  • mastra-ai/mastra#16976: Changes the tool-history write path to persist failed tool executions as tool-invocation entries with state: 'output-error' and errorText in the same llm-mapping-step.ts code points.
  • mastra-ai/mastra#17422: Extends tool execution failure handling by preserving tool-invocation messages in output-error and converting them during Mastra v1/AIV4 conversions.

Suggested labels

complexity: medium, tests: green ✅

Suggested reviewers

  • abhiaiyer91
  • TylerBarnes
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(core): preserve tool execution error state' is concise (46 chars), uses imperative mood, proper capitalization, and directly summarizes the main objective of fixing tool execution error handling.
Linked Issues check ✅ Passed All linked issue requirements are met: tool errors now stored as 'output-error' with 'errorText' (#15569 Bug 1), conversion paths handle 'output-error' state, and regression tests added.
Out of Scope Changes check ✅ Passed All changes are within scope: modifications address tool error state persistence (#15569), legacy compatibility, and corresponding test coverage without introducing unrelated alterations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@littlewwwhite littlewwwhite marked this pull request as ready for review June 9, 2026 15:44
@dane-ai-mastra dane-ai-mastra Bot added the complexity: medium Medium-complexity PR label Jun 9, 2026
@dane-ai-mastra

dane-ai-mastra Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

PR triage

Linked issue check passed (#15569).

Mastra uses CodeRabbit for automated code reviews. Please address all feedback from CodeRabbit by either making changes to your PR or leaving a comment explaining why you disagree with the feedback. Since CodeRabbit is an AI, it may occasionally provide incorrect feedback.


PR complexity score

Factor Value Score impact
Files changed 9 +18
Lines changed 341 +18
Author merged PRs 1 -1
Test files changed Yes -10
Final score 25

Applied label: complexity: medium


Changed test gate

Changed Test Gate is pending. The Changed Test Gate / changed-tests check will update the test label when it completes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

complexity: medium Medium-complexity PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool execution errors stored as successful results — lost on history reload

1 participant