hashicorp/nomad · error
invalid digest format
Error message
invalid digest format
What it means
Returned by newChecksumValidatingReader in api/ioutil.go when the digest string does not contain a '=' separator (checked with strings.SplitN(digest, "=", 2)). This library expects digests in 'algorithm=value' form (e.g. 'sha-256=abc123'); anything else is rejected before any hashing is set up.
Source
Thrown at api/ioutil.go:43
// checksum is the base64 component of checksum
checksum string
// hash is the hashing function used to compute the checksum
hash hash.Hash
}
// newChecksumValidatingReader returns a checksum-validating wrapper reader, according
// to a digest received in HTTP header
//
// The digest must be in the format "<algo>=<base64 of hash>" (e.g. "sha-256=gPelGB7...").
//
// When the reader is fully consumed (i.e. EOT is encountered), if the checksum don't match,
// `Read` returns a checksum mismatch error.
func newChecksumValidatingReader(r io.ReadCloser, digest string) (io.ReadCloser, error) {
parts := strings.SplitN(digest, "=", 2)
if len(parts) != 2 {
return nil, errors.New("invalid digest format")
}
algo := parts[0]
var hash hash.Hash
switch algo {
case "sha-256":
hash = sha256.New()
case "sha-512":
hash = sha512.New()
default:
return nil, errors.New("unsupported checksum format")
}
return &checksumValidatingReader{
r: r,
algo: algo,
checksum: parts[1],
hash: hash,View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the digest string passed to newChecksumValidatingReader/Snapshot contains an '=' separator in 'algo=value' form
- Log/inspect the raw digest header from the server; strip any quotes or whitespace mangling
- Normalize the digest before passing it in, e.g. prefix with 'sha-256=' if only the hash is available
- If the server uses an unsupported header form, compute the digest client-side instead
Example fix
// before
r, err := newChecksumValidatingReader(resp.Body, resp.Header.Get("Digest"))
// after
digest := resp.Header.Get("Digest")
if !strings.Contains(digest, "=") {
digest = "sha-256=" + digest
}
r, err := newChecksumValidatingReader(resp.Body, digest) Defensive patterns
Strategy: validation
Validate before calling
func digestLooksValid(digest string) bool {
parts := strings.SplitN(digest, "=", 2)
return len(parts) == 2 && parts[0] != "" && parts[1] != ""
} Try / catch
r, err := newChecksumValidatingReader(body, digest)
if err != nil {
return fmt.Errorf("digest %q rejected: %w", digest, err)
} Prevention
- Always transmit digests as 'algo=value' per RFC 3230
- Log the raw digest header when this error fires
- Guard against proxies stripping/rewriting the Digest header
- Unit-test the reader with malformed digests
When it happens
Trigger: Calling Snapshot (or any API path that wires a checksum-validated body reader) with a Content-Digest header or digest argument that has no '=' character, e.g. a bare hex hash 'abc123...' or an empty string.
Common situations: A proxy or middleware strips or rewrites the Content-Digest header; the server sends a checksum in a non-standard format; a custom test harness passes a raw hash value instead of the RFC 3230 digest expression.
Related errors
- unsupported checksum format
- failed checking integrity of snapshot: %v
- must pass non-nil job
- job is missing ID
- ErrLockConflict
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/7178c9e41f51ebf6.
Report an issue: GitHub.