Skip to content

Commit f1a6079

Browse files
committed
fix(libsync): clear stale lock token on 412 and 423 upload errors.
When a file path changes (due to a parent folder rename), any WebDAV lock token stored in the journal becomes invalid because tokens are bound to the original URL. A subsequent upload sends an If: header with the stale token, and the server replies 412 (Precondition Failed) or 423 (Locked). Clear the token from the journal on either status code so the next sync retries without it. Schedule rediscovery on 412 since the server state is uncertain. Assisted-by: Claude Sonnet 4.6 <[email protected]> Signed-off-by: Camila Ayres <[email protected]>
1 parent 898748b commit f1a6079

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

src/libsync/propagateupload.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -689,12 +689,25 @@ void PropagateUploadFileCommon::commonErrorHandling(AbstractNetworkJob *job)
689689
QString errorString = job->errorStringParsingBody(&replyContent);
690690
qCWarning(lcPropagateUpload) << replyContent; // display the XML error in the debug
691691

692-
if (_item->_httpErrorCode == 412) {
693-
// Precondition Failed: Either an etag or a checksum mismatch.
692+
if (_item->_httpErrorCode == 412 || _item->_httpErrorCode == 423) {
693+
// 412 Precondition Failed: etag/checksum mismatch or stale lock token.
694+
// 423 Locked: server-side lock held by someone else, or our token is stale.
695+
// A stale lock token (path changed under a moved parent) causes both. Clear it
696+
// so the next sync does not retry with an invalid token.
697+
if (!_item->_lockToken.isEmpty()) {
698+
SyncJournalFileRecord record;
699+
if (propagator()->_journal->getFileRecord(_item->_file, &record) && record.isValid()) {
700+
record._lockstate._lockToken.clear();
701+
if (const auto result = propagator()->_journal->setFileRecord(record); !result) {
702+
qCWarning(lcPropagateUpload) << "Failed to clear stale lock token for" << _item->_file << result.error();
703+
}
704+
}
705+
_item->_lockToken.clear();
706+
}
694707

695-
// Maybe the bad etag is in the database, we need to clear the
696-
// parent folder etag so we won't read from DB next sync.
697-
propagator()->_journal->schedulePathForRemoteDiscovery(_item->_file);
708+
if (_item->_httpErrorCode == 412) {
709+
propagator()->_journal->schedulePathForRemoteDiscovery(_item->_file);
710+
}
698711
propagator()->_anotherSyncNeeded = true;
699712
}
700713

0 commit comments

Comments
 (0)