golang/go · error

errUnrefData

errUnrefData

Error message

archive/tar: sparse file contains unreferenced data

What it means

errUnrefData (unexported) is returned when the dense data stream contains MORE bytes than the sparse map references — i.e. there are bytes in the stream that no sparse data fragment covers, so they would be silently dropped. Like errMissData it signals an internally inconsistent sparse entry and is returned by both the reader and writer paths.

Source

Thrown at src/archive/tar/common.go:40

	"strconv"
	"strings"
	"time"
)

// BUG: Use of the Uid and Gid fields in Header could overflow on 32-bit
// architectures. If a large value is encountered when decoding, the result
// stored in Header will be the truncated version.

var tarinsecurepath = godebug.New("tarinsecurepath")

var (
	ErrHeader          = errors.New("archive/tar: invalid tar header")
	ErrWriteTooLong    = errors.New("archive/tar: write too long")
	ErrFieldTooLong    = errors.New("archive/tar: header field too long")
	ErrWriteAfterClose = errors.New("archive/tar: write after close")
	ErrInsecurePath    = errors.New("archive/tar: insecure file path")
	errMissData        = errors.New("archive/tar: sparse file references non-existent data")
	errUnrefData       = errors.New("archive/tar: sparse file contains unreferenced data")
	errWriteHole       = errors.New("archive/tar: write non-NUL byte in sparse hole")
	errSparseTooLong   = errors.New("archive/tar: sparse map too long")
)

type headerError []string

func (he headerError) Error() string {
	const prefix = "archive/tar: cannot encode header"
	var ss []string
	for _, s := range he {
		if s != "" {
			ss = append(ss, s)
		}
	}
	if len(ss) == 0 {
		return prefix
	}
	return fmt.Sprintf("%s: %v", prefix, strings.Join(ss, "; and "))

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Re-fetch the archive and validate checksum.
  2. When writing sparse entries, ensure the total bytes you push equals sum(sparse fragments) and matches Header.Size minus the hole regions.
  3. Quarantine the entry on errUnrefData; do not retry — the sparse map and data disagree.
  4. For untrusted input, log and skip rather than attempting repair.

Example fix

// before
hdr := &tar.Header{
  Size: 20,
  Sparses: []tar.SparseEntry{{Offset: 0, NumBytes: 5}}, // under-declared
tw.WriteHeader(hdr)
tw.Write(make([]byte, 20)) // throws errUnrefData

// after
hdr := &tar.Header{
  Size: 20,
  Sparses: []tar.SparseEntry{{Offset: 0, NumBytes: 20}},
}
tw.WriteHeader(hdr)
tw.Write(make([]byte, 20))
Defensive patterns

Strategy: validation

Validate before calling

var sum int64
for _, s := range hdr.Sparses { sum += s.NumBytes }
if sum != hdr.Size {
  return fmt.Errorf("sparse fragments sum %d != Size %d (unref data risk)", sum, hdr.Size)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "sparse file contains unreferenced data") {
  log.Printf("corrupt sparse entry %q; skipping", hdr.Name)
  continue
}

Prevention

When it happens

Trigger: Reading a sparse tar entry whose dense data length exceeds the sum of sparse data fragments; writing a sparse entry where the bytes pushed exceed the sum of declared fragment lengths (extra trailing bytes).

Common situations: Corrupted sparse archive; truncated or extended download; hand-built sparse Header whose Sparses array underestimates the data to be written.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/30a8fb8dfbb92625. Report an issue: GitHub.