#5693: fix(chat): display error messages when LLM requests fail
app: android
app: web-ui
size: S
## Summary
- Display formatted error messages in webchat UI instead of blank assistant bubbles when API requests fail
- Add `errorMessage` and `stopReason` field decoding to native iOS/macOS Swift app
- Add `errorMessage` and `stopReason` field decoding to Android Kotlin app
- Parse JSON error payloads and extract user-friendly messages (e.g., "HTTP 401: invalid x-api-key")
## Test plan
- [x] Verified webchat displays error message instead of blank bubble
- [x] Swift build passes
- [x] Swift tests pass (5/6, 1 pre-existing failure)
- [x] TypeScript tests pass (4925 tests)
Fixes #4418
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR improves chat UX across web and native clients by surfacing a formatted, user-friendly error message when an LLM request fails, instead of rendering an empty assistant bubble. It adds `stopReason`/`errorMessage` decoding to Android (Kotlin) and iOS/macOS (Swift) chat models, and updates the webchat text extraction logic to fall back to formatted errors when message content is empty.
The overall approach fits the codebase’s “resilient transcript decoding” philosophy: clients accept additional fields and tolerate multiple message formats while keeping the rendering logic lightweight.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge and should improve UX, with a few edge-case rendering/serialization concerns to verify.
- Changes are localized and additive (new fields + error formatting) and don’t alter request/transport logic. Main risk is UI logic that may override non-text content on error messages and potential mismatch between encoded key casing vs decoded formats in Swift models.
- apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift; apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift; apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageViews.kt; ui/src/ui/chat/message-extract.ts
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#3721: fix(ui): webchat not displaying chat responses
by maxmaxrouge-rgb · 2026-01-29
82.1%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
78.8%
#7316: fix: /chat dashboard performance
by felipcsousa · 2026-02-02
76.4%
#6521: fix: addressed style issue for chat compose and thread on mobile
by spencer-rafada · 2026-02-01
76.3%
#15110: fix: enable auto-scroll during assistant response streaming
by jwchmodx · 2026-02-13
76.1%
#12974: fix: intermittent (no output) reported by users
by vincentkoc · 2026-02-10
75.9%
#16733: fix(ui): avoid injected newlines when tool output is hidden
by jp117 · 2026-02-15
75.4%
#2716: Fix #2678: markdown horizontal rules not rendering in web chat
by Ambar-13 · 2026-01-27
75.3%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
75.2%
#8742: fix(webchat): hide internal system messages from UI (#7440)
by revenuestack · 2026-02-04
75.0%