Skip to content

Conversation

@mrjo118
Copy link
Contributor

@mrjo118 mrjo118 commented Nov 5, 2025

As per my comment at #13611 (comment)

It is possible in a certain scenario for the conflict mechanism to be bypassed, creating no conflict when conflicting changes are synced. This results in data loss unless the user notices the missing changes and checks for them in the note history. This scenario is not dependent on there being time drift between devices running the Joplin client, but is simply dependent on the timing of which the sync runs when using multiple Joplin clients. The problem is most likely to affect users that use multiple Joplin clients concurrently, or frequently switch between clients.

Reproduction steps:

  1. Make a change to a note on client A, sync it, then make another change and don't sync it (or shut down the client altogether)
  2. On client B, sync the latest changes, before client A has had chance to sync
  3. Switch back to client A and sync the change which was not synced before
  4. Switch back to client B, make a change to a note and then sync it - this will overwrite the change without making a conflict
  5. Switch back to client A and sync. The original change made on this client is lost

The issue occurs because the upload step of sync relies on a comparison of if (remoteContent.updated_time > local.sync_time), where the sync time may be greater than the remoteContent.updated_time if the sync has since been run on another client with a new change to the note for that client.

This PR resolves the issue, by setting the sync_time to the remote item updated_time when the sync downloads a remote change (in the delta step and in conflict resolution), similar to when the sync uploads changes, which sets sync_time to the local item updated_time. However, as the remote item updated_time will originate from the local time of other devices in most cases, the setting of the sync_time also caps the value at the current device time. This is to prevent potential sync issues, in cases where there is time drift between devices.

This fixes #13611

Testing

See video:

fix.missing.conflict.scenario.mp4

This demonstrates normal sync working correctly and the conflict resolution working correctly when applying the reproduction steps, using 3 Joplin clients (simulated by switching between profiles) and additionally making a conflict again on the same note, when syncing an un-synced change which was made before the first conflict occurred. I have also tested that note deletion and conflict resolution when a note is deleted on one client is working correctly, and verified the behaviour matches existing, when enabling encryption and syncing the encrypted notes with an existing client.

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.

Concurrent version mismatch overwrite

1 participant