Skip to content

Fix ItemSync item disappearance with cloud-synced directories - #3605

Merged
hluk merged 2 commits into
masterfrom
fix/itemsync-cloud-item-disappearance
May 29, 2026
Merged

hluk merged 2 commits into
masterfrom
fix/itemsync-cloud-item-disappearance

Conversation

@hluk

@hluk hluk commented May 17, 2026 •

Copy link
Copy Markdown
Owner

Handle file operation failures gracefully when sync files are locked by a cloud agent (OneDrive, Dropbox, etc.) or an SMB/CIFS mount.

Changes

Retry transient file errors (commit 6cc0e74)

Add a short retry loop (3 attempts, 20ms apart) around every file operation
in the sync plugin — open, rename, copy, and remove. Cloud sync agents and
network filesystems briefly lock files, and a single failed attempt was enough
to cause data loss or empty reads. Qt's error codes are operation-typed
(OpenError, RenameError, etc.), not cause-typed, so transient locks cannot be
distinguished from permanent errors; we unconditionally retry since the
per-site overhead is small. Retries block the UI thread — a single call site
sleeps at most 40ms, but compound operations may accumulate more.

Each retry is logged as a warning for diagnostics.

Cross-tab copy error handling

Cross-tab file copy now returns success/failure with rollback, matching the
rename path. Previously, failed copies silently updated the model to point at
non-existent files, causing data loss when moving items between tabs.

Logging for previously silent failures

File open failures during item reads now emit warnings. File removal failures
during cleanup only warn when the file still exists afterward (not when the
file was already gone).

Graceful rename failure handling (commit ff3783c, prior work)

Skip updating the model when a rename fails, keeping the item consistent with
its files on disk. Distinguish locked files from genuinely deleted ones to
avoid removing items whose files are merely temporarily unreadable.

Closes #3368
Closes #3579

Assisted-by: Claude (Anthropic)

@codecov

codecov Bot commented May 17, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 51.57895% with 46 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.40%. Comparing base (5111f55) to head (43a76a1).
⚠ïļ Report is 53 commits behind head on master.

Files with missing lines Patch % Lines
plugins/itemsync/filewatcher.cpp 51.57% 46 Missing ⚠ïļ

❌ Your patch status has failed because the patch coverage (51.57%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3605      +/-   ##
==========================================
- Coverage   74.56%   74.40%   -0.16%     
==========================================
  Files         253      253              
  Lines       37816    37896      +80     
  Branches     5107     5117      +10     
==========================================
  Hits        28198    28198              
- Misses       9618     9698      +80     

☔ View full report in Codecov by Harness.
ðŸ“Ē Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄ïļ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • ðŸ“Ķ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hluk
hluk force-pushed the fix/itemsync-cloud-item-disappearance branch 4 times, most recently from 02eef88 to c2d2b2c Compare May 21, 2026 06:11
@hluk
hluk requested a review from Copilot May 29, 2026 07:35
Handle file rename failures gracefully when sync files are locked by a
cloud agent (OneDrive, Dropbox, etc.). Skip updating the model when a
rename fails, keeping the item consistent with its files on disk.

Also avoid removing items when their files are present in the directory
listing but cannot be opened, distinguishing locked files from genuinely
deleted ones.

Update AGENTS.md/CLAUDE.md with explicit Xvfb/openbox setup instructions.

Closes #3368

Assisted-by: Claude (Anthropic)

Copilot AI left a comment

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.

Pull request overview

Fixes data loss in the ItemSync plugin when sync directories are managed by cloud agents (OneDrive, Dropbox) or live on SMB/CIFS mounts, where files can be briefly locked. The plugin now retries transient file operation failures, gracefully handles rename/copy failures with rollback, and skips model updates when files exist on disk but cannot be read (rather than deleting the item).

Changes:

  • Add a retryFileOp helper (3 attempts, 20ms apart) wrapping every file open/rename/copy/remove call in the sync plugin, with debug logging on each retry.
  • Make moveFormatFiles/copyFormatFiles return success/failure with rollback (reverse renames, delete copies); renameMoveCopy now skips model updates on failure to keep state consistent with disk.
  • When updateItems finds files on disk but can't read them, log and skip rather than removing the row from the model; warn on previously-silent open and remove failures.
  • Documentation: expand AGENTS.md with explicit Xvfb/openbox setup steps required before running copyq or tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
plugins/itemsync/filewatcher.cpp Adds retry helper and applies it across all file operations; introduces rollback in cross-tab copy/rename; preserves items whose files exist but fail to read.
AGENTS.md Documents X11/Wayland session setup required to run the app and tests.

ðŸ’Ą Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Cloud sync agents (OneDrive, Dropbox) and SMB/CIFS mounts briefly lock
files, causing file operations to fail for short periods. A single failed
attempt was enough to lose clipboard data or silently drop items.

Changes:
- Add retry logic (3 attempts, 20ms apart) for all file operations in
  the sync plugin. Qt maps all failure causes to the same operation-typed
  error codes (OpenError, RenameError, etc.) so transient locks cannot be
  distinguished from permanent errors; we unconditionally retry. Note that
  retries block the UI thread — a single call site sleeps at most 40ms,
  but compound operations (e.g. rename with copy-fallback across multiple
  format files) may accumulate more.
- Log each retry attempt as a warning for diagnostics
- Cross-tab item copy now detects and rolls back on failure instead of
  silently updating the model to reference non-existent files
- File removal during cleanup now logs warnings instead of failing
  silently, reducing stale file accumulation on cloud directories
- File open failures during item reads are now logged instead of
  returning empty data silently

Fixes: #3368, #3579

Assisted-by: Claude (Anthropic)
@hluk
hluk force-pushed the fix/itemsync-cloud-item-disappearance branch from c2d2b2c to 43a76a1 Compare May 29, 2026 07:39
@hluk
hluk merged commit f670082 into master May 29, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants