nextcloud/server · error · Sabre\DAV\Exception\BadRequest
No hash provided.
Error message
No hash provided.
What it means
validateHash() needs either oc-checksum ('algo:hash') or x-file-md5 with a non-empty value. Reaching its else-branch means both were passed as empty strings - which happens when readPartHeaders()' isset() checks pass because the headers exist but hold empty values ('X-File-MD5:' with nothing after the colon).
Source
Thrown at apps/dav/lib/BulkUpload/MultipartRequestParser.php:242
// Read '\r\n'.
stream_get_contents($this->stream, 2);
return $content;
}
/**
* Compute the MD5 or checksum hash of the next x bytes.
* TODO: Drop $md5 argument when the latest desktop client that uses it is no longer supported.
*/
private function validateHash(int $length, string $fileMd5Header, string $checksumHeader): void {
if ($checksumHeader !== '') {
[$algorithm, $hash] = explode(':', $checksumHeader, 2);
} elseif ($fileMd5Header !== '') {
$algorithm = 'md5';
$hash = $fileMd5Header;
} else {
throw new BadRequest('No hash provided.');
}
$context = hash_init($algorithm);
hash_update_stream($context, $this->stream, $length);
fseek($this->stream, -$length, SEEK_CUR);
$computedHash = hash_final($context);
if ($hash !== $computedHash) {
throw new BadRequest("Computed $algorithm hash is incorrect ($computedHash).");
}
}
}
View on GitHub (pinned to ecdeb153ff)
Solutions
- Always compute and send a real digest - the endpoint requires integrity verification, an empty value is as bad as none
- Only build the header line after the hash value is known, never emit a bare 'Header:' placeholder
- If you control a buggy middleware stripping header values, fix it there
Example fix
// before
"X-File-MD5: $maybeUndefinedVar\r\n" // emits 'X-File-MD5: ' when unset
// after
"X-File-MD5: " . hash('md5', $content) . "\r\n" Defensive patterns
Strategy: validation
Validate before calling
// Never emit an empty hash header
if (!isset($md5) || $md5 === '') {
$md5 = hash('md5', $content); // compute instead of sending blank
}
$partHeader = "X-File-MD5: {$md5}\r\n"; Prevention
- Omit-or-fill: never send a hash header with an empty value
- Compute the digest at payload-build time, right after the content bytes are final
- Note the server only checks isset() at first, so blank values fail later with a different message
When it happens
Trigger: A bulk-upload part with a hash header that is present but blank, e.g. 'X-File-MD5:\r\n' or 'OC-Checksum: \r\n'; isset() in readPartHeaders() lets it through, then validateHash() rejects it with HTTP 400.
Common situations: Template code emitting header names with unfilled placeholders; clients sending the header name unconditionally and only filling it when a checksum was computed.
Related errors
- The hash headers must not be null.
- Computed $algorithm hash is incorrect ($computedHash).
- An error occurred while checking content
- Boundary not found where it should be.
- An error occurred while reading headers of a part
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/e99b6b7483643bbf.
Report an issue: GitHub.