← Back to PRs

#9248: Fix: Webchat UI goes grey/unresponsive after Slack message tool calls

by vishaltandale00 open 2026-02-05 01:52 View on GitHub →
app: web-ui stale
## Summary Fixes webchat UI becoming unresponsive (grey screen) after agent executes Slack message tool calls. Adds defensive error handling to prevent UI crashes when tool results contain large or circular-reference objects. ## Root Cause When the Slack message tool executes, it may return API response objects containing: - **Circular references** in nested objects - **Very large nested objects** (>100KB when stringified) These are passed as `entry.args` directly into `buildToolStreamMessage()` and then rendered in the UI. When the browser's renderer encounters circular refs or excessively large objects during rendering, it throws an exception that breaks the UI rendering loop, causing the grey screen. ## Solution ### 1. Added `sanitizeForDisplay()` function Tests `JSON.stringify()` before passing args to the UI: - Detects circular references → replaces with `"[Circular reference]"` - Detects large objects (>100KB) → replaces with `"[Large object: X bytes]"` - Returns sanitized copy safe for rendering ### 2. Added try-catch around `buildToolStreamMessage()` Catches any unexpected errors and creates a minimal fallback message to keep the UI responsive instead of crashing. ## Implementation **File changed:** `ui/src/ui/app-tool-stream.ts` ```typescript function sanitizeForDisplay(value: unknown): unknown { try { const str = JSON.stringify(value); if (str.length > 100_000) { return \`[Large object: \${str.length} bytes]\`; } return JSON.parse(str); } catch (err) { if (err instanceof Error && err.message.includes("circular")) { return "[Circular reference]"; } return "[Unable to display]"; } } ``` ## Testing **Before fix:** 1. Open webchat at `http://127.0.0.1:18789` 2. Ask agent: "send a test message to #general in Slack" 3. Agent executes `message` tool with `channel=slack` 4. ❌ UI goes grey/unresponsive, requires refresh **After fix:** 1. Same steps as above 2. ✅ UI remains responsive 3. ✅ Tool result displays (or shows sanitized placeholder if too large) 4. ✅ No refresh needed ## Impact - ✅ Webchat remains responsive after Slack tool calls - ✅ Tool results display correctly (or with clear error message) - ✅ No data loss - only affects display sanitization - ✅ Backward compatible - does not affect non-Slack tools - ✅ Fixes issue for all tools that might return large/circular data (Discord, Teams, etc.) ## Related Issue Fixes #9228 --- **Environment tested:** - OpenClaw version: 2026.2.2-3 - Browser: Chrome 144.0 - OS: macOS/Linux <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR hardens the webchat tool-stream rendering path so the UI doesn’t crash (grey/unresponsive) when tool calls return arguments that are not safe to render (e.g., circular references or extremely large nested objects). It introduces a `sanitizeForDisplay()` step before embedding `entry.args` into the `toolcall` content, and adds a defensive `try/catch` around `buildToolStreamMessage()` in `handleAgentEvent()` to fall back to a minimal tool message instead of breaking the render loop. Overall this fits into the existing `handleAgentEvent()` flow by ensuring `entry.message` is always set to a renderable structure before `syncToolStreamMessages()` propagates it to `host.chatToolMessages`. <h3>Confidence Score: 4/5</h3> - This PR is mostly safe to merge, but has a couple correctness/UX edge cases in the new defensive fallback logic. - Core change is localized to tool-stream message construction and adds guards against known crash causes. Remaining concerns are limited to misclassification in serialization fallback and the catch-path emitting an incorrect toolresult during non-result phases, which can confuse UI state. - ui/src/ui/app-tool-stream.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs