Repository navigation
Conversation
matt2e
force-pushed
the
errors/user-copy-messages
branch
from
November 9, 2026 16:06
4b2e055 to
32c31dc
Compare
…the relay's words
Add userCopy(error, context) in features/relay. It classifies a failure
by the typed errors Buzz already produces (ReadError kind and status,
ApiPaused/ApiCapacity, UploadError, PublishRejected/PublishNotSent,
fetch's network TypeErrors, DOMException names) and returns { text,
retry, kind, details }. text is the site's own sentence plus a plain
next step and never carries an exception name, HTTP status, URL or raw
relay or native string; those stay in details. ErrorDetails renders
details under a collapsed "Details" disclosure.
The relay layer keeps failures typed instead of stringified:
- The service snapshot stores a RelayFailure ({ kind, details }) and
channel windows and thread snapshots keep a WindowFailure. History
parse failures are ReadError("invalid-response").
- The window store records errorSource "older" only when loadOlder
failed, so a head or catch-up failure no longer blames older history.
- PublishNotSent carries the relay's wait for a quota hint or a held
lane, so busy copy can say how long.
- Copy and retry share one set of fetch network messages (including
WebKit's), and a body cut off after its headers is an unavailable read.
- An answer Buzz can't use is not retried at once. The service asks
again in the background after 30 s, 1, 2 and every 5 minutes, keeping
the failure on screen meanwhile.
History reads: ChannelBody, ChannelTimeline, NewMessage, ThreadPanel,
MediaReviewViewer and DraftPreview map the failure with historyFailure():
"Messages didn’t load." with "Try again" for an outage or 5xx; "Buzz is
busy. Try again in a few seconds." (or "in about N minutes/hours") when
paused; "Check for updates" and no Try again for a 4xx or invalid
answer; "You don’t have access to this conversation." for a refusal with
no known reason. The older edge says "Older messages didn’t load.".
Connection failures: Workflows and Notes show the Messages
ConnectionFailed card: "Can’t connect", "Check your connection. We’ll
keep trying." and "Try again".
An answer Buzz can't use reads "Buzz couldn’t connect to this
community." with "Check for updates"; a refusal shows the community
refusal title with no retry. Bestie, Pinned Bestie, Activity, its
preview and Reminders say the same through connectionFailureText and
connectionFailureAction. App's page failure cards put the primary
action last and drop Try again for an unusable connection.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: mtoohey <mtoohey@squareup.com>
Five journeys still asserted the copy that the previous commit replaced: - thread-window: the older-replies alert said "Older page failed"; it now says "Older replies didn’t load." (ThreadPanel's OlderRepliesFailure). - media-controls, message-overlays, gallery-theme: MediaReviewViewer's unavailable-media button was "Retry"; it is "Try again". The message-overlays title and the gallery comment follow the rename. - navigation-repairs: the keyboard hand-off journey failed the session with an empty JSON object. That is now an answer Buzz can't use, so the card says "Buzz couldn’t connect to this community." and offers Check for updates, not Try again. The journey now fails the broker registration with a recorded 502 instead, a failure the service leaves for the user, so the card still says "Check your connection, then try again." and offers Try again. Every caller registers the community, so every registration fails until the user acts, and the retry is counted from then on. Product copy is unchanged. Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
matt2e
force-pushed
the
errors/user-copy-messages
branch
from
November 12, 2026 23:50
32c31dc to
0e35fbc
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Failed history reads and failed community connections showed the relay's or browser's own text: exception names (
ReadError:), HTTP statuses (Relay request failed (400)) and raw relay strings (rate-limited: quota exceeded; retry in 3600s). This adds one shared helper,userCopy(error, context), which turns the typed failures Buzz already produces into a plain sentence, a retry flag and raw details. It also adopts the helper on every history-read surface and on the connection failure of Workflows, Notes and the status-line pages.This is the base of a stack. #3097 (uploads), #3098 (profile save) and #3099 (page and panel crashes) target this branch and reuse the helper.
What changed
Shared helper and typed failures
userCopy(error, context)(src/features/relay/user-copy.ts) classifies by type:ReadErrorkind and status,ApiPaused/ApiCapacity,UploadError,PublishRejected/PublishNotSent, fetch's networkTypeErrors andDOMExceptionnames. It never parses text it doesn't own.textnever carries an exception name, status, URL or raw string; those go indetails.ErrorDetails(src/shared/ErrorDetails.tsx) rendersdetailsunder a collapsed Details disclosure. Only the page crash card in fix(pages): offer Try again and name the plugin when a page or panel crashes #3099 uses it. History and connection failures show no Details.RelayFailure({ kind, details }) instead ofString(error). Channel windows and thread snapshots keep aWindowFailure, and history parse failures areReadError("invalid-response").errorSource: "older"only whenloadOlderfailed, so a head, catch-up or seek failure no longer reads as older history failing.PublishNotSentcarries the relay's wait (quota hint or held lane), so busy copy can say how long.unusable, e.g. a 404 or 400 from an edge) is not retried at once. The service asks again in the background after 30 s, then 1, 2 and every 5 minutes. The failure stays on screen meanwhile.History reads (ChannelBody, ChannelTimeline, NewMessage, ThreadPanel, MediaReviewViewer, DraftPreview)
Relay request failed (503)+ Retry messagesMessages didn’t load.+ Try againRelay request failed (400)+ Retry messagesMessages didn’t load.+ Check for updates (no Try again)rate-limited: quota exceeded; retry in 3600s+ Retry messagesMessages didn’t load. Buzz is busy. Try again in about 1 hour.+ Try again (… Try again in a few seconds.for a minute or less)Messages didn’t load. You don’t have access to this conversation.Relay request failed (400)+ Retry older messagesOlder messages didn’t load.+ Try again or Check for updatesCould not load conversation.+ Retry conversationMessages didn’t load.+ Try again or Check for updatesOlder replies didn’t load./This attachment didn’t load., with Try again only when retrying can helpConnection failures
Connect to a community to browse workflows./ReadError: Relay read failed (502)+ Retry connectionCan’t connect/Check your connection. We’ll keep trying.+ Try againConnect to a community to read notes./ReadError: Relay read failed (502)+ Retry connectionReadError: Relay read failed (404)+ Retry connectionCan’t connect/Buzz couldn’t connect to this community.+ Check for updates (Messages' card says the same)ReadError: Relay read failed (403)+ Retry connectionYou don’t have access to this community, no retryReadError: Relay read failed (404)+ Retry connectionBuzz couldn’t connect to this community.+ Check for updates; a failure that may clear saysCheck your connection. We’ll keep trying.+ Retry connectionCould not connect., no buttonConnect to a community to …now shows only when there is genuinely no connection.App page failure cards (
App.tsx) put the quiet action first and the primary action last. Copy and visibility are unchanged, except that an unusable connection now gets the update sentence above and no Try again:<Plugin>is turned off: Go to Messages, then Manage pluginsBefore / After
Head read answered 400:
Relay request failed (400)+ Retry messages becomesMessages didn’t load.+ Check for updates, because the same read fails every time. There is no Details.Head read answered 503: the same sentence, with Try again because a retry can help.
Older page answered 400:
Older messages didn’t load.with Check for updates in place of Retry older messages. (Round 1 capture; this copy is unchanged since.)Older page answered 503:
Older messages didn’t load.with Try again. (Round 1 capture; this copy is unchanged since.)Busy, a 429 with "retry in 3600s": the relay's text becomes
Buzz is busy. Try again in about 1 hour.Older capture (round 2): it still shows a Details disclosure under the button, which was removed later. The shipped history failure has no Details.Workflows with a 502: the raw
ReadErrorand "Connect to a community" are replaced by the MessagesCan’t connectcard with Try again.Workflows with a 404, an answer this Buzz can't use:
Buzz couldn’t connect to this community.with Check for updates instead of a retry that would fail the same way.Notes with the same 502: the same card instead of "Connect to a community to read notes." Older capture (round 1): it still shows a Details disclosure under the card, which was removed later. The shipped card has no Details.
Workflows when the community refuses the account (403): the refusal title with no retry, instead of a raw 403 and Retry connection. (Round 1 capture; this state is unchanged since.)
Activity with a 404: the status line gets Check for updates instead of Retry connection. Older capture (round 2): it still reads "… Updating Buzz may fix this."; that sentence was dropped, and the shipped text is only
Buzz couldn’t connect to this community.Bestie with a 404: the raw
ReadErrorbecomes the update sentence and Check for updates. Older capture (round 2): it still reads "… Updating Buzz may fix this."; the shipped text is onlyBuzz couldn’t connect to this community.Checks
pnpm typecheck: clean on this branch.pnpm lint: exit 0, with 30 infos that predate this change.biome formatis clean on the changed files.history-loading,live-status,new-message) are included but not run on this snapshot. Hosted CI is the first full run.Known gaps
🤖 Generated with Claude Code