Skip to content

[WebDAV] Regression: zero-byte PUT returns 500 (Drive API 400) on v1.6.7, blocking Synology Hyper Backup #656

Description

@elshaio

Summary

Internxt WebDAV CLI v1.6.7 currently fails to create zero-byte files.

A WebDAV PUT with Content-Length: 0 reaches DriveFileService.createFile(), but the Internxt Drive API returns HTTP 400. The WebDAV server then exposes this as HTTP 500.

This completely blocks the creation of new Synology Hyper Backup repositories because Hyper Backup performs a zero-byte PUT for synobkpinfo.db while validating or initializing the destination.

This appears to be a regression of:

The same Synology Hyper Backup setup successfully initialized a new repository on July 31, 2026, using the same v1.6.7 Docker image. It began failing on August 5, 2026.

Environment

  • NAS: Synology DS920+

  • Architecture: x86_64

  • DSM: 7.3.2-86009 Update 4

  • Hyper Backup: 4.2.2-4262

  • Client: Synology Hyper Backup

  • WebDAV URL: https://127.0.0.1:3005

  • Container image: internxt/webdav:latest

  • Internxt CLI version: 1.6.7

  • Image ID:

    sha256:86376b663a71468bf40d9dd41f85f068ca9733b579e472d097b9610b9afbbabe
    
  • Image digest:

    internxt/webdav@sha256:0bbeb8aa397184a7ff4cb76c7e6e688a24d23b076d6de86e71d8d0e91825d43f
    
  • Image creation date:

    2026-07-09T09:57:02.973036198Z
    
  • Container creation date:

    2026-07-31T22:04:52.534691138Z
    

The container had:

status=running
restarts=0
oom=false

Authentication to Internxt Drive succeeds, and the server reports itself online. Credentials and account email have been omitted.

Why this blocks Synology Hyper Backup

When creating a new WebDAV destination, Hyper Backup performs this sequence:

  1. PROPFIND on the destination.
  2. MKCOL to create the .hbk repository directory.
  3. PUT synobkpinfo.db with a zero-byte body.
  4. If that succeeds, it continues creating repository metadata.
  5. If it fails repeatedly, Hyper Backup deletes the newly created .hbk directory and reports that the destination cannot be used or is already in use.

The failure happens at step 3.

Example from the Internxt WebDAV log:

[PUT] /HyperBackup/NAHS_1.hbk/synobkpinfo.db - Start (0B)
[PUT] Request received for file at /HyperBackup/NAHS_1.hbk/synobkpinfo.db
[PUT] Uploading 'synobkpinfo.db' (0 B) to '/HyperBackup/NAHS_1.hbk/'
[ERROR MIDDLEWARE] [PUT - /HyperBackup/NAHS_1.hbk/synobkpinfo.db] Request failed with status code 400
Stack: Error: Request failed with status code 400
    at HttpClient.normalizeError
    at async HttpClient.post
    at async DriveFileService.createFile
    at async handle (/app/dist/webdav/handlers/PUT.handler.js:82:22)
[PUT] /HyperBackup/NAHS_1.hbk/synobkpinfo.db - 500

Hyper Backup retries this operation several times. It eventually cleans up the partial repository:

[DELETE] Request received for item at /HyperBackup/NAHS_1.hbk
[DELETE] Trashing folder
[DELETE] Folder trashed successfully
[DELETE] /HyperBackup/NAHS_1.hbk - 204

The corresponding Hyper Backup messages are:

Exception occurred while backing up data.
Backup task was suspended (suspension incomplete).
Failed to start backup task.
Scheduled backup has been skipped because Hyper Backup cannot resume/discard the task.

Adding fewer source folders does not help because the failure occurs during repository initialization, before backup data selection matters.

Minimal reproduction without Hyper Backup

The issue can be reproduced directly against the WebDAV server. The certificate is local/self-signed, hence curl -k.

1. Create an isolated test folder

DAV_TEST='https://127.0.0.1:3005/HyperBackup/__dav_probe_20260805'

curl -skS -i -X MKCOL "$DAV_TEST/"

Result:

HTTP/1.1 201 Created

2. Upload a zero-byte file

curl -skS -i -X PUT \
  -H 'Content-Type: application/octet-stream' \
  -H 'Content-Length: 0' \
  --data-binary '' \
  "$DAV_TEST/empty.bin"

Result:

HTTP/1.1 500 Internal Server Error
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<D:error xmlns:D="DAV:">
  <D:responsedescription>
    Request failed with status code 400
  </D:responsedescription>
</D:error>

Corresponding WebDAV log:

2026-08-05T16:09:24.594Z [PUT] /HyperBackup/__dav_probe_20260805/empty.bin - Start (0B)
2026-08-05T16:09:24.955Z [PUT] Request received for file at /HyperBackup/__dav_probe_20260805/empty.bin
2026-08-05T16:09:24.963Z [PUT] Uploading 'empty.bin' (0 B)
2026-08-05T16:09:28.882Z [ERROR MIDDLEWARE] Request failed with status code 400
2026-08-05T16:09:28.883Z [PUT] /HyperBackup/__dav_probe_20260805/empty.bin - 500

3. Upload a one-byte file to the same destination

curl -skS -i -X PUT \
  -H 'Content-Type: application/octet-stream' \
  --data-binary 'x' \
  "$DAV_TEST/one-byte.bin"

Result:

HTTP/1.1 201 Created
Content-Length: 0

Corresponding log:

[PUT] Uploading 'one-byte.bin' (1 B)
[PUT] File uploaded to network
[PUT] File uploaded to Internxt Drive
[PUT] [RESPONSE-201]

4. Download the one-byte file

curl -skS -i "$DAV_TEST/one-byte.bin"

Result:

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-length: 1

x

5. Remove the test directory

curl -skS -i -X DELETE "$DAV_TEST/"

Result:

HTTP/1.1 204 No Content

What this reproduction rules out

The controlled test demonstrates that:

  • The local WebDAV server is reachable.
  • TLS connectivity works.
  • Internxt authentication works.
  • Folder creation works.
  • Non-empty file creation works.
  • File download works.
  • Folder deletion works.
  • The problem does not depend on Hyper Backup itself.
  • The failure is specifically triggered by a zero-byte file.
  • The upstream HTTP 400 happens inside DriveFileService.createFile().

The WebDAV bridge should not return HTTP 500 for this request because v1.6.7 contains explicit zero-byte file support.

Evidence that it previously worked with the same image

The Hyper Backup support logs show that the original repository was completely new and was initialized on July 31, 2026.

The Docker container was created at:

2026-07-31T22:04:52.534691138Z

The Hyper Backup task was created approximately ten minutes later:

2026-07-31T17:14:46-05:00

Therefore, the original task used the same v1.6.7 container from its first initialization. There was no older Internxt image involved.

During the original task creation, Synology recorded:

2026-07-31T17:15:33-05:00 WebDAVUpload:
https://127.0.0.1:3005/Hyper%20Backup/NAHS_1.hbk/synobkpinfo.db

2026-07-31T17:15:43-05:00 WebDAVUpload:
https://127.0.0.1:3005/Hyper%20Backup/NAHS_1.hbk/Control/%40writer/v1.1.-1.0.0.none.none.cinfo

2026-07-31T17:15:54-05:00 WebDAVUpload:
https://127.0.0.1:3005/Hyper%20Backup/NAHS_1.hbk/_Syno_TaskConfig

2026-07-31T17:16:07-05:00 WebDAVDownload:
https://127.0.0.1:3005/Hyper%20Backup/NAHS_1.hbk/synobkpinfo.db

This sequence progressed successfully beyond synobkpinfo.db, and Hyper Backup subsequently uploaded approximately 236 GiB of a new initial backup.

The initial backup ran for approximately 69.5 hours and created many .bucket.2 and .index.2 objects before later becoming suspended.

The container was not recreated between the successful initialization and the later failure. It was only restarted on August 5:

created=2026-07-31T22:04:52.534691138Z
started=2026-08-05T15:44:18.998791183Z
image_id=sha256:86376b663a71468bf40d9dd41f85f068ca9733b579e472d097b9610b9afbbabe

This strongly suggests a server-side regression or a compatibility change in the Drive API rather than a Docker image change.

Additional Hyper Backup failures

Before the new-repository test, the original task also encountered repeated HTTP 500 responses while uploading objects such as:

/Hyper Backup/NAHS_1.hbk/Pool/0/2/716.index.2

It also later failed while creating or updating writer keep-alive objects:

/Hyper Backup/NAHS_1.hbk/Control/lock/lock_keep_alive.@writer_version_0.<uuid>

Hyper Backup retried these requests with exponential backoff and then suspended the task. There were 82 WebDAV HTTP 500 occurrences in the collected Hyper Backup log.

These may be separate symptoms of the same Drive API regression, although the zero-byte failure is independently reproducible.

Relevant implementation

The empty-file support added for #285 intentionally:

  1. Accepts Content-Length: 0.
  2. Skips the network content upload.
  3. Calls DriveFileService.createFile() using:
size: 0
fileId: undefined

That exact createFile() operation is now being rejected by the Drive API with HTTP 400.

The currently published Docker image is v1.6.7 and uses:

@internxt/sdk 1.17.13

The current repository branch identifies itself as v1.6.8 and uses:

@internxt/sdk 1.19.0

However, as of August 5, 2026, Docker Hub still publishes v1.6.7 as latest.

It is possible that the Drive backend now requires behavior present in the newer SDK, but this is only a hypothesis.

Expected behavior

A zero-byte WebDAV request such as:

PUT /path/empty.bin
Content-Length: 0

should return:

HTTP/1.1 201 Created

A subsequent GET, HEAD, or PROPFIND should expose a file with a length of zero.

Synology Hyper Backup should then be able to finish destination validation and initialize synobkpinfo.db.

Actual behavior

The CLI accepts the WebDAV request but DriveFileService.createFile() receives HTTP 400 from the Internxt Drive API. The CLI maps this to HTTP 500, causing Hyper Backup to retry, suspend and delete the partially created destination.

Questions

  1. Did the Drive API behavior for zero-byte entries change between July 31 and August 5, 2026?
  2. Is this a regression of Can not upload zero byte (empty) file #285 / PR [PB-4953]: feat/enable-empty-file-upload-support #446?
  3. Does @internxt/sdk 1.19.0 contain a required fix for the current Drive API?
  4. Can an updated v1.6.8 Docker image be published so this can be tested?
  5. Can the underlying Drive API response body be logged instead of only Request failed with status code 400?
  6. Could a zero-byte WebDAV integration test be added to prevent this regression?
  7. Is Synology Hyper Backup expected to be supported through Internxt WebDAV?

I can provide additional sanitized Hyper Backup or WebDAV logs if required. The complete Synology support archive contains private system information and will not be attached publicly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions