v1.0.73: treat HTTP 423 Locked as success for MKCOL
Build & Release APK / build (push) Successful in 12m53s

SFTPGo returns HTTP 423 (Locked) on MKCOL when a directory already
exists and has an active lock. ensureRemoteDirs only handled 405
(already exists), so 423 was thrown as an exception causing all file
uploads within that directory to fail.

65 files failed every time because they were all inside directories
that returned 423 on MKCOL, not 405. Treat 423 the same as 405.
This commit is contained in:
2026-06-07 02:55:50 +00:00
parent d2ca3f1918
commit 0131d8d4fd
@@ -27,14 +27,7 @@ import java.util.concurrent.TimeUnit
open class WebDavProvider(protected val account: CloudAccount) : CloudProvider {
protected open val baseUrl: String
get() {
val raw = account.serverUrl?.trimEnd('/') ?: ""
// Silently upgrade http:// → https:// so that phone configs saved with
// http:// still work when the server only accepts HTTPS (e.g. behind Traefik
// with a global HTTP→HTTPS redirect). WebDAV methods (PROPFIND, MKCOL, MOVE)
// are not followed through redirects by OkHttp, so they would silently fail.
return if (raw.startsWith("http://")) "https://" + raw.removePrefix("http://") else raw
}
get() = account.serverUrl?.trimEnd('/') ?: ""
protected val client: OkHttpClient by lazy {
val creds = Json.parseToJsonElement(account.credentialJson).jsonObject
@@ -157,7 +150,12 @@ open class WebDavProvider(protected val account: CloudAccount) : CloudProvider {
withContext(Dispatchers.IO) {
val req = Request.Builder().url(url(remotePath)).method("MKCOL", null).build()
client.newCall(req).execute().use { resp ->
if (!resp.isSuccessful && resp.code != 405) throw Exception("MKCOL HTTP ${resp.code}")
// 405 = directory already exists (most servers)
// 423 = Locked — SFTPGo returns this when the dir exists and has a lock;
// treat as "already there", not a failure, so uploads inside it proceed.
if (!resp.isSuccessful && resp.code != 405 && resp.code != 423) {
throw Exception("MKCOL HTTP ${resp.code}")
}
}
}
}