Chunked uploads not working. Failed migration?

This is NC16.0.9, it started life perhaps six years ago and was upgraded all the way to where we are now.

So another one of the usual “uploads not working” threads. I looked at all the previous ones and have been able to discard the usual possibilities such as Nginx configuration issues and PHP upload file limits. What I did see while looking at the errors was this:

20. /nextcloud/apps/dav/lib/Upload/ChunkingPlugin.php line 77
    Sabre\DAV\Tree->move("uploads/fuicui/1871329941/.file", "files/fuicui/fi ... t")
21. /nextcloud/apps/dav/lib/Upload/ChunkingPlugin.php line 56
    OCA\DAV\Upload\ChunkingPlugin->performMove("uploads/fuicui/1871329941/.file", "files/fuicui/fi ... t")
22. <<closure>>
    OCA\DAV\Upload\ChunkingPlugin->beforeMove("uploads/fuicui/1871329941/.file", "files/fuicui/fi ... t")
23. /nextcloud/3rdparty/sabre/event/lib/EventEmitterTrait.php line 105
    undefinedundefinedcall_user_func_array([OCA\DAV\Upload\ ... "], ["uploads/fuicui ... "])
24. /nextcloud/3rdparty/sabre/dav/lib/DAV/CorePlugin.php line 633
    Sabre\Event\EventEmitter->emit("beforeMove", ["uploads/fuicui ... "])

Leaving aside the undefinedundefinedcall_user_func_array bit, dodgy as it looks, what caught my attention was that the directory uploads/fuicui/… does not exist! Not even while uploading. When the chunked upload is in progress what does temporarily exist is nextcloud/data/fuicui/uploads/ with contents:


In other words, the username and the uploads literal are the wrong way around, and the expected .file file does not exist. The structure is completely different than what those ChunkingPlugin methods appear to be expecting.

How is that possible?

So turns out that it was all down to Nextcloud being rather idiosyncratically unable to cope with files named *.part, of which I had a few.

Just in case I dug out the docs describing chunked uploads and tried it by hand via Dolphin’s webdavs and curl. It works as described.

Now the sync client seems to work also, with the same files as before, as long as you do not call them something that it doesn’t like, in which case it will throw a completely random error message at you.