Skip to content

Report tool call failures as UI errors#3113

Open
RitwijParmar wants to merge 1 commit into
onlook-dev:mainfrom
RitwijParmar:codex/onlook-tool-error-results
Open

Report tool call failures as UI errors#3113
RitwijParmar wants to merge 1 commit into
onlook-dev:mainfrom
RitwijParmar:codex/onlook-tool-error-results

Conversation

@RitwijParmar

@RitwijParmar RitwijParmar commented May 26, 2026

Copy link
Copy Markdown

Summary

  • report browser-side tool execution failures as AI SDK output-error tool results instead of normal output strings
  • add a small shared helper for formatting tool-call errors and producing typed error results
  • keep the chat execution state from getting stuck when addToolResult fails by clearing isExecutingToolCall in finally
  • update the stream regression test to use the AI SDK v5 output-error state

Why

Issue #2766 asks for tool results to carry an error string so the UI can render tool failures separately from successful results. The UI already passes errorText into ToolOutput, but handleToolCall was catching failures and sending "error handling tool call ..." as a normal output. That makes parse failures, unavailable tools, sandbox errors, and thrown client-tool failures look like successful tool output in the transcript.

This change preserves the existing success path while making failures first-class UI errors, so the chat can show the red error block and the next agent turn can distinguish a failed tool execution from a successful result string.

Closes #2766

Verification

  • npm exec --package bun@1.3.1 -- bun test packages/ai/test/tools/result.test.ts
  • npm exec --package bun@1.3.1 -- bun test packages/ai/test/stream/convert.test.ts
  • npm exec --package bun@1.3.1 -- bun --filter @onlook/web-client typecheck
  • git diff --check

Note: bun --filter @onlook/ai typecheck still fails on existing repo alias/test typing issues unrelated to this change (for example unresolved @/trpc/client imports from web-client files referenced by the AI package and pre-existing test typing errors).

Summary by CodeRabbit

  • Bug Fixes

    • Improved tool call error handling to ensure UI state properly resets even when tool execution fails.
    • Enhanced error reporting for tool execution results with more consistent and standardized error handling.
  • Tests

    • Added test coverage for tool result error handling and formatting.

Review Change Stack

@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs-onlook Skipped Skipped May 26, 2026 11:09pm

Request Review

@vercel vercel Bot temporarily deployed to Preview – docs-onlook May 26, 2026 23:09 Inactive
@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown

@RitwijParmar is attempting to deploy a commit to the Onlook Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces discriminated result types and structured error handling for tool calls. A new result.ts module defines ToolOutputResult and ToolErrorResult shapes, error formatting utilities, and an AddToolResult callback type. The handleToolCall function refactored to use these types with explicit try/catch reporting instead of string-based errors. The useChat hook updated to use finally() for proper state cleanup. Tests added for new helpers and existing error-state assertions updated.

Changes

Tool Error Result Handling

Layer / File(s) Summary
Result type contracts and helper functions
packages/ai/src/tools/result.ts, packages/ai/src/tools/index.ts
New module defines ToolOutputResult and ToolErrorResult discriminated types, exports AddToolResult callback type, introduces formatToolCallError() to normalize unknown errors, and createToolErrorResult() to construct error results. Wildcard re-export added to tools index.
handleToolCall refactoring to structured error reporting
apps/web/client/src/components/tools/tools.ts
Function signature updated to accept AddToolResult instead of inline callback. Control flow changed from store-output-then-report-in-finally to await-success-in-try and await-error-in-catch using createToolErrorResult(), replacing string-based error fallback.
useChat promise state cleanup
apps/web/client/src/app/project/[id]/_hooks/use-chat/index.tsx
Updated onToolCall handler from .then() to .finally() so setIsExecutingToolCall(false) clears on both success and rejection of handleToolCall(...).
Tests for result helpers and error state expectations
packages/ai/test/tools/result.test.ts, packages/ai/test/stream/convert.test.ts
New test suite for formatToolCallError() and createToolErrorResult() covering error normalization and result structure. Existing stream/convert tests updated to expect output-error state instead of error.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • onlook-dev/onlook#2929: Modifies handleToolCall function signature and refactors tool-result reporting paths in the same file.
  • onlook-dev/onlook#2846: Changes tool-call wiring in use-chat's onToolCall and refactors handleToolCall result reporting including error handling.
  • onlook-dev/onlook#2837: Overlaps on use-chat control flow and handleToolCall refactoring for tool-call result/state updates.

Suggested reviewers

  • Kitenite

Poem

🐰 Errors now have names and voices clear,
No more silent fails that disappear,
Result shapes dance in harmony,
Finally blocks let loading states run free!
The tool pipeline's refactored, true and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title accurately and concisely summarizes the main change: reporting tool call failures as UI errors instead of normal output.
Description check ✅ Passed The PR description is comprehensive and well-structured with a clear summary, rationale, and verification steps, though missing formal sections from the template.
Linked Issues check ✅ Passed The PR successfully implements the objective from #2766 by introducing error results with output-error state and error formatting utilities for UI distinction.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #2766 objectives: error result types, error formatting, and state management for UI error rendering.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ai/src/tools/result.ts`:
- Around line 28-31: The function formatToolCallError currently returns
JSON.stringify(error) which yields "undefined" for undefined inputs; change
formatToolCallError to detect undefined/null or non-stringifiable errors and
return a stable constant like "Unknown tool error" instead of the string
"undefined" (use this constant when JSON.stringify(error) is falsy or equals
"undefined"); also update the related unit test to expect "Unknown tool error"
for missing/unknown tool errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a53bfce-1a69-40d4-aae1-9f812e540a1e

📥 Commits

Reviewing files that changed from the base of the PR and between a242be5 and 2320f5b.

📒 Files selected for processing (6)
  • apps/web/client/src/app/project/[id]/_hooks/use-chat/index.tsx
  • apps/web/client/src/components/tools/tools.ts
  • packages/ai/src/tools/index.ts
  • packages/ai/src/tools/result.ts
  • packages/ai/test/stream/convert.test.ts
  • packages/ai/test/tools/result.test.ts

Comment on lines +28 to +31
try {
return JSON.stringify(error) ?? String(error);
} catch {
return String(error);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant code in the reviewed file
sed -n '1,120p' packages/ai/src/tools/result.ts

# Find all call sites of formatToolCallError
rg -n "formatToolCallError\s*\(" -S packages/ai/src/tools/result.ts packages/ai/src packages | head -n 200

Repository: onlook-dev/onlook

Length of output: 1959


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the unit tests that mention formatToolCallError(undefined)
sed -n '1,120p' packages/ai/test/tools/result.test.ts

# Find call sites of createToolErrorResult (and formatToolCallError if any outside this file)
rg -n "createToolErrorResult\s*\(" packages/ai/src packages/ai/test packages | head -n 200
rg -n "formatToolCallError\s*\(" packages/ai/src packages/ai/test packages | head -n 200

Repository: onlook-dev/onlook

Length of output: 2588


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for usages of errorText to see how it's displayed
rg -n "errorText" packages/ai/src packages | head -n 200

# Search for formatToolCallError usage elsewhere
rg -n "formatToolCallError\s*\(" packages | head -n 200

# Search for output-error state handling (likely UI/consumers)
rg -n "state:\s*'output-error'|output-error" packages | head -n 200

Repository: onlook-dev/onlook

Length of output: 2567


Use a stable fallback message for missing/unknown tool errors

formatToolCallError(undefined) currently returns 'undefined' (via JSON.stringify(undefined) ?? String(undefined)), and UI renders truthy errorText directly—there’s also a unit test asserting this behavior. Return a constant (e.g., 'Unknown tool error') instead and update the test accordingly.

Suggested patch
 export function formatToolCallError(error: unknown): string {
@@
     try {
-        return JSON.stringify(error) ?? String(error);
+        return JSON.stringify(error) ?? 'Unknown tool error';
     } catch {
-        return String(error);
+        return 'Unknown tool error';
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/src/tools/result.ts` around lines 28 - 31, The function
formatToolCallError currently returns JSON.stringify(error) which yields
"undefined" for undefined inputs; change formatToolCallError to detect
undefined/null or non-stringifiable errors and return a stable constant like
"Unknown tool error" instead of the string "undefined" (use this constant when
JSON.stringify(error) is falsy or equals "undefined"); also update the related
unit test to expect "Unknown tool error" for missing/unknown tool errors.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] Tool results should have and error string so UI can show tool errors

1 participant