restic/restic · critical
header decoding failed: %w
Error message
header decoding failed: %w
What it means
The self-check performed right after encrypting a pack header failed at its first step: List() could not decode the header bytes that were just encrypted. A freshly encrypted header is by construction valid, so a decode failure practically means the bytes changed in memory between Seal and verify - the symptom restic associates with hardware faults or software bugs.
Source
Thrown at internal/repository/pack/pack.go:138
return p.err
}
if n != len(encryptedHeader) {
p.err = errors.New("wrong number of bytes written")
return p.err
}
p.bytes += uint(len(encryptedHeader))
return nil
}
func verifyHeader(k *crypto.Key, header []byte, expected []Blob) error {
// do not offer a way to skip the pack header verification, as pack headers are usually small enough
// to not result in a significant performance impact
decoded, hdrSize, err := List(k, bytes.NewReader(header), int64(len(header)))
if err != nil {
return fmt.Errorf("header decoding failed: %w", err)
}
if hdrSize != uint32(len(header)) {
return fmt.Errorf("unexpected header size %v instead of %v", hdrSize, len(header))
}
if len(decoded) != len(expected) {
return fmt.Errorf("pack header size mismatch")
}
for i := range decoded {
if decoded[i] != expected[i] {
return fmt.Errorf("pack header entry mismatch got %v instead of %v", decoded[i], expected[i])
}
}
return nil
}
// HeaderOverhead returns an estimate of the number of bytes written by a call to Finalize.
func (p *Packer) HeaderOverhead() int {
return crypto.CiphertextLength(0) + binary.Size(uint32(0))View on GitHub (pinned to a80be1478a)
Solutions
- Run a memory test (memtest86+) and verify system stability under load
- Retry the backup; if it fails again on the same data, suspect hardware
- Update to the latest restic release before further debugging
- If reproducible on stable hardware, report it with the wrapped error and debug logs
Defensive patterns
Strategy: try-catch
Type guard
func isHeaderDecodeFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "header decoding failed")
} Try / catch
if err := verifyHeader(k, encryptedHeader, blobs); err != nil {
if isHeaderDecodeFailure(err) {
// freshly encrypted data failed to decode: abort and collect hardware diagnostics
return abortWithDiagnostics(err)
}
return err
} Prevention
- Treat any verifyHeader failure as a hardware alarm, not a data problem
- Test RAM and cooling after the first occurrence
- Report reproducible cases with the wrapped error to the restic tracker
- Avoid aggressive RAM overclocking on machines producing backups
When it happens
Trigger: Bit flips in RAM or CPU caches during the finalize path; failing storage for temporary buffers; a bug in the crypto or packer layer of that restic version.
Common situations: Large backups on unstable or overclocked machines; recurring finalize failures on one host; virtualization memory issues.
Related errors
- unexpected header size %v instead of %v
- pack header size mismatch
- Detected data corruption while writing pack-file header: %w
- pack header entry mismatch got %v instead of %v
- pack %v: %v
AI-assisted analysis of restic/restic@a80be1478a (2026-08-15).
Data as JSON: /api/errors/9f3797a1bccb4e0e.
Report an issue: GitHub.