kopia/kopia · error
unable to write header
Error message
unable to write header
What it means
This error wraps a failed Write of the v2 index header (a 17+ byte binary header) to the underlying writer w during index Finish. The header includes version, key length, entry count, pack ID count, format-info count and base timestamp; if writing those bytes fails, the error is wrapped with "unable to write header" so the failure point is identifiable. The root cause is whatever the underlying writer reported.
Solutions
- Inspect the wrapped cause with %+v to see the underlying write error (ENOSPC, EPIPE, file closed, etc.).
- Check available disk space and quotas on the destination volume; free space or redirect the index output.
- Ensure the writer is valid and open for the whole duration of the Finish call.
- Retry the index build after fixing the storage condition; the index was not fully written.
Defensive patterns
Strategy: try-catch
Validate before calling
// check writable space before building:
if stat, err := outDirStat(); err != nil || stat.freeBytes() < estimatedIndexSize {
return errors.New("insufficient space for index output")
} Try / catch
if err := idxBuilder.Finish(w); err != nil && strings.Contains(err.Error(), "unable to write header") {
log.Errorf("index header write failed: %+v", err) // inspect wrapped cause
} Prevention
- Monitor free disk space on the index output volume.
- Keep the writer open for the whole Finish duration.
- Write to a local temp file, then move into place atomically.
- Unwrap and log the cause (%+v), not just the wrapper message.
When it happens
Trigger: Any io.Writer error returned by w.Write(header) in the v2 index Finish path — disk full, closed writer, broken pipe to a pipe/network sink, or permission issues on the output file.
Common situations: Running out of disk space while committing an index, writing to an already-closed buffer, or streaming the index to a destination that disappeared mid-write.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- error writing format info entry
- unable to write entry
- ErrInvalidOffset
- error appending
- error closing index file
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/ba02ec7762ea9b32.
Report an issue: GitHub.
Appendix: source
Thrown at repo/content/index/index_v2.go:525
}
uniqueFormatInfo2IndexLen := len(b2.uniqueFormatInfo2Index)
if uniqueFormatInfo2IndexLen > maxUInt8 {
return errors.Errorf("invalid unique format v2 info index length: %v", uniqueFormatInfo2IndexLen)
}
// write header
header := make([]byte, v2IndexHeaderSize)
header[0] = Version2 // version
header[1] = byte(b2.keyLength) //nolint:gosec // range checked above
binary.BigEndian.PutUint16(header[2:4], uint16(b2.entrySize)) //nolint:gosec
binary.BigEndian.PutUint32(header[4:8], uint32(b2.entryCount)) //nolint:gosec
binary.BigEndian.PutUint32(header[8:12], uint32(len(b2.packID2Index))) //nolint:gosec
header[12] = byte(uniqueFormatInfo2IndexLen)
binary.BigEndian.PutUint32(header[13:17], uint32(b2.baseTimestamp)) //nolint:gosec
if _, err := w.Write(header); err != nil {
return errors.Wrap(err, "unable to write header")
}
// write sorted index entries
for _, it := range sortedInfos {
if err := b2.writeIndexEntry(w, it); err != nil {
return errors.Wrap(err, "unable to write entry")
}
}
// write pack ID entries in the index order of values from packID2Index (0, 1, 2, ...).
reversePackIDIndex := make([]blob.ID, len(b2.packID2Index))
for k, v := range b2.packID2Index {
reversePackIDIndex[v] = k
}
// emit pack ID information in this order.
for _, e := range reversePackIDIndex {
if err := b2.writePackIDEntry(w, e); err != nil {View on GitHub (pinned to 82495e54b5)