Skip to content

fix(chat): surface real backend errors instead of the canned empty-response hint - #125

Open
sergiomaldo wants to merge 1 commit into
LegalQuants:mainfrom
sergiomaldo:fix/chat-error-passthrough
Open

fix(chat): surface real backend errors instead of the canned empty-response hint#125
sergiomaldo wants to merge 1 commit into
LegalQuants:mainfrom
sergiomaldo:fix/chat-error-passthrough

Conversation

@sergiomaldo

Copy link
Copy Markdown

Problem

When the backend refuses or fails a chat completion, the web UI either shows nothing or misdiagnoses it:

  • A gateway refusal (observed: 403 tier_below_minimum from a skill-declared tier floor) renders no error bubble and no toast — the send arrow greys out and the composer just sits there. The user cannot distinguish "slow local inference" from "request refused", even though the 403 body carries an actionable message ("Pick a model with an equal or lower-numbered tier, or relax the floor").
  • When an error is shown, arbitrary api failures map onto one canned hint ("The model returned an empty response. This can happen with smaller local models...") — observed for an api-side 400 validation rejection on a cloud-model request, actively pointing the user at the wrong cause.

Repro: attach a skill whose tier floor exceeds the selected model's tier and send a message; or trigger any non-400 api error on send.

Fix

  • ChatMessage gains errorCode; setError/applyFrame propagate the SSE error frame's code, and the non-2xx POST path parses the FastAPI detail envelope ({code, message} or plain string) for any status, not just 400.
  • The generic network-failure catch keeps the underlying message visible.
  • Message.svelte renders [code] message in the existing error styling, including for a done-but-errored empty turn; the canned empty-response hint now only appears when a stream genuinely completed with no error and no content.
  • Retry/decide clear errorCode along with error.

Tests

New cases in chatStream.svelte.test.ts (error-frame code propagation, non-2xx envelope parsing for multiple statuses, network-failure message) and Message.svelte.test.ts (code+message rendering, errored empty turn, canned hint only on genuine empty success).

Provenance

Found operating a production self-hosted legal deployment (a law firm running Donna v0.6.2 fully local).

CI note: prettier --check currently fails on main itself (docs/superpowers/HANDOFF-v0.6.2-release.md); #122 fixes it, so this branch's lint job goes green once that lands. svelte-check, eslint, and vitest all pass on this branch.

🤖 Generated with Claude Code

…sponse hint

Error frames and api error envelopes carry a code + human message, but the
UI dropped the code and, in errored-empty turns, showed the misleading
'model returned an empty response' hint. Now:
- ChatMessage gains errorCode; setError/applyFrame propagate the SSE error
  frame's code, and the non-2xx POST path parses the FastAPI detail envelope
  ({code, message} or plain string) for ANY status, not just 400
- the generic network-failure catch keeps the underlying message visible
- Message.svelte renders '[code] message' in the existing error styling, also
  for a done-but-errored empty turn, and only shows the canned empty-response
  hint when a stream genuinely completed with no error and no content
- retry/decide clear errorCode along with error

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant