Skip to content

Fix side-chat "Message not sent: CancelledError" and its misleading turn error - #776

Open
myles332 wants to merge 3 commits into
mainfrom
myles/side-chat-send-failures
Open

myles332 wants to merge 3 commits into
mainfrom
myles/side-chat-send-failures

Conversation

@myles332

Copy link
Copy Markdown
Contributor

Summary

A side-chat user saw "This turn did not finish. / Message not sent: CancelledError" under a turn that had actually completed, and that turn's answer was hidden under "Worked for 1m 21s".

  • Send no longer fails on a cancelled history read. Before sending, the composer waits for the chat history query. A concurrent invalidation (most likely the SSE reconnect refetch of live families) cancels a read joined by fetchQuery, so it rejected with CancelledError. The wait now retries on CancelledError while the workspace scope is current and the session is not deleted. The retry joins the replacement fetch, or reads the cache after a revert cancel.
  • Local send failures stand on their own. localError messages (send, resend and fork-switch failures) now carry LOCAL_ERROR_PART_ID. They start their own response group, so they no longer become the previous turn's "answer", and they render as a one-line notice instead of TurnStatusRow's "This turn did not finish."

Test plan

  • node --test UI suite (433/433), including a new grouping test
  • tsc --noEmit, i18n check, vite build (ui/dist regenerated)
  • cargo fmt --check, cargo clippy -D warnings, cargo build --locked, cargo test --locked
  • In the app: force a send failure and confirm a standalone "Message not sent: …" notice appears, while the previous answer stays visible and is not marked unfinished
  • In the app: send while the SSE stream reconnects and confirm the message goes through

🤖 Generated with Claude Code

myles332 and others added 2 commits October 23, 2026 18:33
…urn error

The send path awaits the chat history query before sending. A concurrent
invalidation (e.g. an SSE reconnect) cancels that joined read, so the send
failed with CancelledError. Retry the wait on cancellation while the scope is
current and the session still exists.

Local dashboard errors were also merged into the preceding assistant response,
which hid that turn's answer under "Worked for" and labelled it "This turn did
not finish." Give them their own group and render them as a plain notice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…failures

# Conflicts:
#	ui/dist/assets/PdfPreview-C7B2nDXs.js
#	ui/dist/assets/PdfPreview-CFkJL2GR.js
#	ui/dist/assets/PdfPreview-DvHMzgEY.js
#	ui/dist/assets/index-Ba-ecrFp.js
#	ui/dist/assets/index-CVY72FgI.js
#	ui/dist/assets/index-V63B47MD.js
#	ui/dist/index.html
@greptile-apps

greptile-apps Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect chat sending and transcript display.

The PR appears safe to merge, with a non-blocking gap in tests for the cancelled-history retry.

Findings

  1. P2 History retries lack test coverage ▶
Fix with agent prompt
### Issue 1
ui/src/components/ChatPanel.tsx:5875-5882
The added test covers grouping, but no test checks that `CancelledError` retries the history read, waits for its replacement, and stops retrying after a workspace change or session deletion. The existing cancellation test still expects rejection and does not supply `CancelledError` or `deletedSessionIds` to its extracted-code test helper.

Add focused tests for these paths so a broken retry cannot silently bring back cancelled sends.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR retries cancelled history reads before sending and separates local failures from completed agent responses.

  • Chat sends retry when a history read is cancelled.
  • Local chat errors appear apart from finished answers.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Send message] --> B[Wait for history]
  B --> C{Read result}
  C -->|Success| D[Send turn]
  C -->|Cancelled| E{Workspace current and session not deleted?}
  E -->|Yes| B
  E -->|No| F[Leave retry path]
  C -->|Other error| F
Loading

Reviews (1) · Last reviewed commit: "Fix side-chat "Message not sent: Cancell..." · Reviewed by Greptile

Comment on lines +5875 to +5882
const awaitHistory = (): Promise<unknown> => queryClient.fetchQuery({
...history,
...(queryClient.getQueryState(history.queryKey)?.fetchStatus === "fetching" ? { staleTime: 0 } : {}),
}).catch((cause: unknown) => {
if (cause instanceof CancelledError && isCurrentScope(sessionsOptions.queryKey) && !deletedSessionIds.has(historySid)) return awaitHistory();
throw cause;
});
await awaitHistory();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 History retries lack test coverage

The added test covers grouping, but no test checks that CancelledError retries the history read, waits for its replacement, and stops retrying after a workspace change or session deletion. The existing cancellation test still expects rejection and does not supply CancelledError or deletedSessionIds to its extracted-code test helper.

Add focused tests for these paths so a broken retry cannot silently bring back cancelled sends.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/ChatPanel.tsx
Line: 5875-5882

Comment:
**History retries lack test coverage**

The added test covers grouping, but no test checks that `CancelledError` retries the history read, waits for its replacement, and stops retrying after a workspace change or session deletion. The existing cancellation test still expects rejection and does not supply `CancelledError` or `deletedSessionIds` to its extracted-code test helper.

Add focused tests for these paths so a broken retry cannot silently bring back cancelled sends.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@myles332 myles332 added the auto-merge Queue for automatic merge once all checks pass label Oct 26, 2026

This branch has not been deployed

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

Labels

auto-merge Queue for automatic merge once all checks pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant