404 error on MOVE-Request when assembling chunked upload

Nextcloud 31.0.6 Snap Package
Ubuntu 24.04.2 LTS | Raspberry Pi 4

Hi,

I’d like to upload large files in chunks as described here to be able to resume interrupted transfers.

Everything works as expected except for the final step where the uploaded chunks should get combined and moved. The process is started by a MOVE request to a hidden file, but I only get the following WebDAV response:

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\NotFound</s:exception>
  <s:message>File with name /1752417557/.file could not be located</s:message>
</d:error>

You can use the test script from one of the original commits to replicate the issue:

`#!/bin/bash
# Usage: ./upload.sh targetname1
# Uploads a file consisting of 3 chunks and downloads it a again to verify the upload

if [ -z "$1" ]
  then
    echo "Usage: ./s3-chunk filepath"
	exit 1
fi

CHUNKSIZE=10
CHUNKS=2
> /tmp/one.testbin
for i in $(seq 1 $CHUNKS)
do
	CHUNKSIZE=$(( $RANDOM % 10 + 5 ))
	dd if=/dev/random of=/tmp/$i.testbin bs=${CHUNKSIZE}M count=1 2>/dev/null
	cat /tmp/$i.testbin >> /tmp/one.testbin
done

ls -l /tmp/*.testbin

SERVER=http://nextcloud.dev.local
USER=admin
PASS=admin
FILENAME=$1
timestamp=$(date +%s)

#echo "=> Cleanup existing file"
#curl -X DELETE -u $USER:$PASS "$SERVER/remote.php/dav/files/$USER/$FILENAME"



DESTINATION="$SERVER/remote.php/dav/files/admin/$FILENAME"

echo "Uploading to $USER:$PASS $SERVER/remote.php/dav/uploads/$USER/$timestamp"
echo "=> MKCOL"
curl -X MKCOL -u $USER:$PASS $SERVER/remote.php/dav/uploads/$USER/$timestamp \
	-H "Destination: $DESTINATION"

echo "=> PUT"
for i in $(seq 1 $CHUNKS | shuf)
do
	echo "- PART $i"
	(curl -X PUT -u $USER:$PASS $SERVER/remote.php/dav/uploads/$USER/$timestamp/$i -T /tmp/$i.testbin -H "X-S3-Multipart-Destination: files/admin/$FILENAME" \
		-H "Destination: $DESTINATION"; echo " - DONE $i") &
done

wait

# exit 1;

echo "=> MOVE"
curl -X MOVE -u $USER:$PASS --header "Destination:$SERVER/remote.php/dav/files/$USER/$FILENAME" $SERVER/remote.php/dav/uploads/$USER/$timestamp/.file \
	-H "Destination: $DESTINATION"

curl -u $USER:$PASS $SERVER/remote.php/dav/files/$USER/$FILENAME > /tmp/compare.testbin

md5sum /tmp/one.testbin
md5sum /tmp/compare.testbin

ls -l /tmp/*.testbin

rm /tmp/*.testbin`

The Nextcloud log file shows the following error:

{
    "app": "webdav",
    "exception": {
        "Code": 0,
        "CustomMessage": "File with name /1752417557/.file could not be located",
        "Exception": "Sabre\\DAV\\Exception\\NotFound",
        "File": "/snap/nextcloud/48756/htdocs/apps/dav/lib/Connector/Sabre/Directory.php",
        "Line": 194,
        "Message": "File with name /1752417557/.file could not be located",
        "Trace": [
            {
                "class": "OCA\\DAV\\Connector\\Sabre\\Directory",
                "file": "/snap/nextcloud/48756/htdocs/3rdparty/sabre/dav/lib/DAV/Tree.php",
                "function": "getChild",
                "line": 95,
                "type": "->"
            },
            {
                "class": "Sabre\\DAV\\Tree",
                "file": "/snap/nextcloud/48756/htdocs/apps/dav/lib/Connector/Sabre/QuotaPlugin.php",
                "function": "getNodeForPath",
                "line": 140,
                "type": "->"
            },
            {
                "class": "OCA\\DAV\\Connector\\Sabre\\QuotaPlugin",
                "file": "/snap/nextcloud/48756/htdocs/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
                "function": "beforeMove",
                "line": 89,
                "type": "->"
            },
            {
                "class": "Sabre\\DAV\\Server",
                "file": "/snap/nextcloud/48756/htdocs/3rdparty/sabre/dav/lib/DAV/CorePlugin.php",
                "function": "emit",
                "line": 603,
                "type": "->"
            },
            {
                "class": "Sabre\\DAV\\CorePlugin",
                "file": "/snap/nextcloud/48756/htdocs/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
                "function": "httpMove",
                "line": 89,
                "type": "->"
            },
            {
                "class": "Sabre\\DAV\\Server",
                "file": "/snap/nextcloud/48756/htdocs/3rdparty/sabre/dav/lib/DAV/Server.php",
                "function": "emit",
                "line": 472,
                "type": "->"
            },
            {
                "class": "Sabre\\DAV\\Server",
                "file": "/snap/nextcloud/48756/htdocs/apps/dav/lib/Connector/Sabre/Server.php",
                "function": "invokeMethod",
                "line": 49,
                "type": "->"
            },
            {
                "class": "OCA\\DAV\\Connector\\Sabre\\Server",
                "file": "/snap/nextcloud/48756/htdocs/apps/dav/lib/Server.php",
                "function": "start",
                "line": 400,
                "type": "->"
            },
            {
                "class": "OCA\\DAV\\Server",
                "file": "/snap/nextcloud/48756/htdocs/apps/dav/appinfo/v2/remote.php",
                "function": "exec",
                "line": 21,
                "type": "->"
            },
            {
                "args": [
                    "/snap/nextcloud/48756/htdocs/apps/dav/appinfo/v2/remote.php"
                ],
                "file": "/snap/nextcloud/48756/htdocs/remote.php",
                "function": "require_once",
                "line": 145
            }
        ],
        "exception": [],
        "message": "File with name /1752417557/.file could not be located"
    },
    "id": "6873c76bba0ad",
    "level": 0,
    "message": "File with name /1752417557/.file could not be located",
    "method": "MOVE",
    "remoteAddr": "192.168.2.345",
    "reqId": "LHm2qSVTqhfoskbL2eHK",
    "time": "2025-07-13T14:39:24+00:00",
    "url": "/remote.php/dav/files/user/1752417557/.file",
    "user": "user",
    "userAgent": "curl/8.5.0",
    "version": "31.0.6.2"
}

My config.php looks like this:

<?php
$CONFIG = array (
  'apps_paths' =>
  array (
    0 =>
    array (
      'path' => '/snap/nextcloud/current/htdocs/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 =>
    array (
      'path' => '/var/snap/nextcloud/current/nextcloud/extra-apps',
      'url' => '/extra-apps',
      'writable' => true,
    ),
  ),
  'supportedDatabases' =>
  array (
    0 => 'mysql',
  ),
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'memcache.local' => '\\OC\\Memcache\\Redis',
  'redis' =>
  array (
    'host' => '/tmp/sockets/redis.sock',
    'port' => 0,
  ),
  'log_type' => 'file',
  'logfile' => '/var/snap/nextcloud/current/logs/nextcloud.log',
  'log_level' => 0,
  'logfilemode' => 416,
  'maintenance_window_start' => 1,
  'instanceid' => 'oc2pu5v1vyml',
  'passwordsalt' => '...',
  'secret' => '...',
  'trusted_domains' =>
  array (
    0 => 'abc.local',
  ),
  'datadirectory' => '/var/snap/nextcloud/common/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '31.0.6.2',
  'overwrite.cli.url' => 'http://abc.local',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost:/tmp/sockets/mysql.sock',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => '...',
  'installed' => true,
  'maintenance' => false,
  'loglevel' => 0,
);

Can anyone suggest what configuration error could prevent the hidden file from being written to the temporary directory where the upload chunks are gathered?

I’m kind of frustrated by now, so thank you very much for your help! :face_with_bags_under_eyes:
Marek