Skip to content

fix(sync): let an object a store can't hand over stop only its own log - #459

Open
A-EDev wants to merge 1 commit into
mainfrom
fix/sync2-one-bad-item
Open

A-EDev wants to merge 1 commit into
mainfrom
fix/sync2-one-bad-item

Conversation

@A-EDev

@A-EDev A-EDev commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

An object, a blob or a wrap that a store can't hand over now stops only itself, as spec/store.md asks under "Contain one bad item", instead of failing the whole sync.

  • An object over the 4 MiB limit came back as a store error, and read_object's ? turned that into a failed sync for every device's changes, every time, on a Flow server and on a WebDAV folder alike.
  • one_item in server.rs reads such a failure as absent: over the size limit, or refused with a 4xx other than 401, 407, 408 and 429. The stores' get_object and key both use it, so log reads, snapshots, blobs, the walk down from a cut and LAN answers all see what they see for a gap. Only log reads have a new test; the others are by reading.
  • A file in a WebDAV roster/ folder that can't be read is ignored like any other file that isn't an entry. It counts towards the folder's limits as a whole object, and isn't fetched again, so many of them can't cost more than the limits allow.
  • A network failure, a 5xx, a refused login, a timeout and a rate limit still fail the sync. So does an over-limit answer that isn't one item, such as a listing.
  • New StoreError::TooLarge, so an over-limit answer can't be confused with a malformed sign-in or other response. The interface shows it like Malformed.

Related issue

None.

Change type

  • Bug fix

Validation

Run on macOS arm64.

  • pnpm test: not run, no frontend file changed
  • pnpm build: not run, no frontend file changed
  • cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check: exit 0
  • cargo clippy --all-targets --all-features in src-tauri: exit 0, no warnings in the files this changes
  • cargo test --no-fail-fast --all-targets --all-features in src-tauri: 1290 passed, 0 failed, 9 ignored
  • I smoke-tested the affected desktop behavior. Nothing ran in a real window.

Before the change, a real WebDAV server holding an object over the limit failed pull with "the server sent an invalid response". The new tests failed the same way.

Checked by breaking the code on purpose, one change at a time, with sync2_webdav and sync2_server:

Change Tests that failed
Over the limit fails the sync again 4
A refusal fails the sync again 2
A 5xx stops only its item 2
A rate limit stops only its item 2
A refused login stops only its item 1
A timeout stops only its item 2
Every failure stops only its item 2
An unreadable roster file costs nothing 1
An unreadable roster file fails the read 2
A server object isn't contained 2
A folder object isn't contained 2
A folder wrap isn't contained 1

Risk and compatibility

  • No format or database change.

  • A store that refuses every object with a 403 now shows as a log that stops rather than as a failed sync, because its listing and its roster still answer. Android's reading of the rule treats a 403 the same way.

  • While a log is held back on the current read, other senders' objects on later pages wait until fix(sync): keep reading other devices past one that stopped #450 lands. A WebDAV folder lists every sender at once, so this only applies to a Flow server's pages.

  • Not run against a real Flow server or Android.

  • No new secrets, private data, telemetry, or broad Tauri permissions were introduced.

  • User-facing documentation was updated where needed. (none needed, the spec already says this)

  • Dependency and lockfile changes are intentional and limited to this PR. (none)

  • Breaking changes and upgrade steps are clearly documented. (none)

Copilot AI balanced review requested due to automatic review settings November 7, 2026 20:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

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.

2 participants