Cloud Sync (WebDAV): uploads succeed on the server but report HTTP -1, so the sync is marked as failed
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 14.1k
- Forks
- 2.2k
- Avg merge
- 7h 35m
- Merged PRs (30d)
- 51
Description
Description
Cloud Sync (WebDAV driver) reports Cloud Sync finished with failures while
every file actually reaches the server. The frontend log shows:
[WARN] [webdav] Failed: manifest.server: HTTP -1
[ERROR] [CloudSync] Uploading updated manifest failed.
but the server's access log for the very same requests shows them succeeding:
"PUT /remote.php/dav/files/<user>/<dir>/manifest.server HTTP/1.1" 201
"PUT /remote.php/dav/files/<user>/<dir>/manifest.server HTTP/1.1" 204
"MKCOL /remote.php/dav/files/<user>/<dir>/saves/ HTTP/1.1" 405
HTTP -1 means net_http never parsed a status line, so webdav_update_cb()
computes success = false even though the upload completed. The user is told
the sync failed and, because task_cloud_sync_update_manifest_cb() only calls
task_cloud_sync_commit_local_manifest() on success, the local manifest is
left stale — which produces spurious Conflicting change of ... on the next
run.
Cause (as far as I could trace it)
net_http.c keeps a connection pool (net_http_conn_pool_add /
net_http_conn_pool_remove). When a pooled connection is reused after the
server has closed it (Apache's default KeepAliveTimeout is 5 s), the read
fails and both error paths set response->status = -1:
/* net_http.c, receive_header_failed / receive_body_failed */
net_http_conn_pool_remove(state->conn);
state->conn = NULL;
state->err = true;
response->part = P_DONE;
response->status = -1;
There is no retry: grep -i retry libretro-common/net/net_http.c returns
nothing. A single transparent retry on a reused connection that fails before
a status line is read is the usual remedy for this, and would not change
behaviour for fresh connections.
Note the driver code itself looks correct — webdav_update_cb() accepts any
2xx and webdav_mkdir_cb() already tolerates the 405 that WebDAV returns for
an existing collection. The problem is that it never receives a status to
judge.
Workaround (server side)
Telling Apache not to keep connections alive for this client removes the
problem completely:
BrowserMatch "libretro" nokeepalive downgrade-1.0 force-response-1.0
Before: ~75 s per sync, several HTTP -1, finished with failures every time.
After: 1.7 s, no failures, Uploading updated manifest succeeded.
This only affects the libretro user agent; everything else keeps HTTP/1.1
with keep-alive.
Steps to reproduce
- WebDAV Cloud Sync against a server with keep-alive enabled (Apache default).
- Sync a directory with enough files that the sync spans more than
KeepAliveTimeoutseconds — the deeper the tree the easier, since the driver
issues oneMKCOLper path component per file. - Some transfers report
HTTP -1although the server logged them as 201/204.
Versions
- RetroArch 1.22.2 (nightly, Windows x64) and the Steam build
- Server: Nextcloud 34 on Apache 2.4.68,
KeepAliveTimeout 5,
MaxKeepAliveRequests 100 - Also reported with other WebDAV servers in the (now closed) #16834, which
showed the sameHTTP -1, suggesting the client rather than any one server.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in libretro-common/net/net_http.c, tracing connection-pool reuse through receive_header_failed and receive_body_failed, then inspect webdav_update_cb() and task_cloud_sync_update_manifest_cb(). Reproduce against a WebDAV server with keep-alive enabled and verify that a reused-connection failure before the status line is read no longer reports HTTP -1, while successful uploads commit the local manifest.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- cloud, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100