nextcloud/server · error · Sabre\DAV\Exception

400

400

Error message

An error occurred while reading headers of a part

What it means

While reading a part's header lines, any line without a ':' cannot be a header and is rejected with HTTP 400. The offending line is logged first ('Header missing ":" on bulk request: ...' in nextcloud.log), which tells you the exact malformed input.

Source

Thrown at apps/dav/lib/BulkUpload/MultipartRequestParser.php:181

	/**
	 * Return the headers of a part of the multipart body.
	 *
	 * @throws Exception
	 * @throws BadRequest
	 * @throws LengthRequired
	 */
	private function readPartHeaders(): array {
		$headers = [];

		while (($line = fgets($this->stream)) !== "\r\n") {
			if ($line === false) {
				throw new Exception('An error occurred while reading headers of a part');
			}

			if (!str_contains($line, ':')) {
				$this->logger->error('Header missing ":" on bulk request: ' . json_encode($line));
				throw new Exception('An error occurred while reading headers of a part', Http::STATUS_BAD_REQUEST);
			}

			try {
				[$key, $value] = explode(':', $line, 2);
				$headers[strtolower(trim($key))] = trim($value);
			} catch (\Exception $e) {
				throw new BadRequest('An error occurred while parsing headers of a part', Http::STATUS_BAD_REQUEST, $e);
			}
		}

		if (!isset($headers['content-length'])) {
			throw new LengthRequired('The Content-Length header must not be null.');
		}

		// TODO: Drop $md5 condition when the latest desktop client that uses it is no longer supported.
		if (!isset($headers['x-file-md5']) && !isset($headers['oc-checksum'])) {
			throw new BadRequest('The hash headers must not be null.');
		}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Open nextcloud.log and read the logged json_encode($line) entry; it shows the exact malformed line and its bytes
  2. Fix the client to emit one flat 'Header-Name: value\r\n' line per header, no folding, no bare lines
  3. Keep headers ASCII with a single colon; regenerate the payload with a maintained multipart library instead of string templates

Example fix

// before
"X-File-Path: /a.txt\r\n"
."  continued-wrongly\r\n" // continuation line has no ':' -> this error

// after
"X-File-Path: /a.txt\r\n" // one flat header per line only
Defensive patterns

Strategy: validation

Validate before calling

// Validate header lines before writing them into the part
foreach ($headers as $key => $value) {
    if (!preg_match('/^[!#$%&\'*+.^_`|~0-9A-Za-z-]+$/', $key)) {
        throw new \InvalidArgumentException("Invalid header name: {$key}");
    }
}

Prevention

When it happens

Trigger: A bulk-upload part containing a header line that is not 'Key: value': a folded/continuation line starting with space or tab, a bare word, or a line whose colon was lost (often due to wrong line-ending handling splitting lines incorrectly).

Common situations: Hand-built multipart bodies; clients emitting RFC 7230 obs-fold style headers that arrive as continuation lines; charset corruption mangling the ':' byte; header names or values with control characters.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/7ff273d2ae2eef9e. Report an issue: GitHub.