File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -983,7 +983,21 @@ export function useStreamingMessage(options: UseStreamingMessageOptions = {}) {
983983
984984 const lifecyclePhase = lifecyclePhaseRef . current as StreamLifecyclePhase
985985 if ( ! finishedRef . current && lifecyclePhase !== 'handoff' ) {
986- finishStream ( )
986+ // If the stream ended cleanly (no 'done' event) but we never received
987+ // any response text, treat it as a failure rather than a successful
988+ // empty completion. This happens when a proxy (e.g., Tailscale Serve)
989+ // closes the connection after an idle timeout — the reader returns
990+ // { done: true } but the model was still generating. Fixes #512.
991+ if (
992+ ! fullTextRef . current &&
993+ ( lifecyclePhase === 'accepted' || lifecyclePhase === 'active' )
994+ ) {
995+ markFailed (
996+ 'Connection closed before response was received. The backend may still be processing — check server logs or retry.' ,
997+ )
998+ } else {
999+ finishStream ( )
1000+ }
9871001 }
9881002 } catch ( err ) {
9891003 if ( ( err as Error ) . name === 'AbortError' ) {
You can’t perform that action at this time.
0 commit comments