Repository navigation
Conversation
A request that names an offer the peer has already replaced or withdrawn is refused, as omacom#43, omacom#63 and omacom#68 require. The refusal was a bare Abort, so the requester failed the paste and the server raised an urgent "Paste of text failed: the peer aborted the transfer" notification. Background readers such as a clipboard history watcher or fcitx5 hit this on every quick pair of copies and on reconnects. ClipboardAbort gains an optional reason. Stale is sent by the serial checks on both sides, the server's own-selection refusal, abort_serving, and the client's read_local refusals. The requester ends the paste as cancelled, which is reported only once shown, but only while no data has arrived: a paste cut after bytes reached the sink still fails. A bare Abort from an older peer is still a failure, and without a reason the message encodes to the same bytes as before. Refs omacom#88 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CMMntVL9C8ejpnzQUUdHHn
[Medium impact] The PR appears safe to merge; no actionable issues were found. SummaryAdds an optional
Acknowledged scope from Unayung: server serial invalidation, the remaining no-selection/missing-mime race, and the crossed-offer tie-break are deferred. The existing server warning remains intentional for this scope. Unayung also notes that out-of-tree
|
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.
Refs #88. This is fix 2 from the issue, scoped as TechLuddite suggested in the comment there.
Problem
When a clipboard request names an offer the peer has already replaced, the peer refuses it with a bare
Abort. The requester can't tell that apart from a real failure, so the paste ends asFailedand the server posts an urgent "Paste of text failed / the peer aborted the transfer" notification. Nobody pasted by hand: the read comes from a background reader on the host (Omarchy's clipboard historywl-paste --watch, fcitx5).I see it on an Omarchy desktop every time a laptop client wakes from sleep and gliff reconnects. The session's clipboard offers change hands within a few seconds, and 2 to 4 urgent notifications arrive 2 to 3 s after the SSH session comes up.
Fix
ClipboardAbort(client and server) gets an optionalreason: Option<AbortReason>at index 1, decoded withcbor::optionalper the rules inmsg.rs.AbortReasonhas one value,Stale.reason: Noneencodes to the same bytes as the old message (820e8107), so an old peer sees no change.Abortfrom an old peer still decodes and still fails.None.Staleis sent where the refusal means "that offer is no longer mine to serve":hypr_input::Error::OwnSelection; its Display text is unchanged.abort_serving(Revoke the local clipboard offer when the clipboard changes #63)read_localrefusals ("withdrawn", "holds the server's offer")receiveerrors stay bare, and so they still fail.StalebecomesTransferError::Stale, andJobs::finishmaps it toState::Cancelled. Cancelled is reported only for a job that was already shown, so a background read refused at once raises nothing.Staleonly while it has received zero bytes. If a serve is cut after data reached the sink (e.g. a large image pasted while the other side copies again), the paste is truncated and is still reported as failed.docs/architecture.mddescribes the reason.Not in this PR
local.serialinon_remote_offer. Without it, case 2 still logs theclipboard receive failed … selection is our ownWARN, but the refusal is now quiet. A narrow race also remains: the server's selection changes beforeon_selectionruns, andreceivethen fails with "no selection" or "selection has no X" and is reported as failed.ClipboardMsg::Abortgains a field, so out-of-tree code that buildsAbort { id }(the macOS client in Add native macOS client and host with LAN discovery #47) needsreason: Noneor the matching reason at its refusal sites.Testing
scripts/check.shpasses. New tests:msg::tests::an_abort_reason_is_optional_on_the_wire: the old bytes, old-peer decode, unknown reasona_stale_refusal_ends_the_paste_quietly: a stale refusal ends with no report, and a bare one ends with one Failed reporta_stale_abort_after_data_is_a_failurea_serve_cut_for_a_stale_offer_says_soprogress::a_stale_refusal_ends_as_cancelledReverting the reason mapping or the zero-bytes guard makes the matching test fail. I did not run
scripts/e2e.shbecause this doesn't touch the video path.The change was written and reviewed with Claude Opus 5.5 agents.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CMMntVL9C8ejpnzQUUdHHn