golang/go · error
ErrWriteTooLong
ErrWriteTooLong
Error message
archive/tar: write too long
What it means
ErrWriteTooLong is returned by the tar Writer when more bytes are written for an entry than declared in its Header.Size, and on Close when the stream still has trailing non-zero bytes after the last entry. The tar format requires each regular-file entry to be exactly Header.Size bytes; overshooting corrupts subsequent headers, so the Writer rejects the extra bytes.
Source
Thrown at src/archive/tar/common.go:35
"io/fs"
"maps"
"math"
"path"
"reflect"
"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)
}View on GitHub (pinned to b6b368adc5)
Solutions
- Set Header.Size to the exact byte length of the data you will write, taken at the moment of writing (re-stat the file).
- Use io.CopyN(tw, src, hdr.Size) to guarantee you never write past the declared size.
- If the source length is unknown, set Size = 0 only if you genuinely want an empty file; otherwise buffer first or use a pipe with accurate length.
- On Close(), ensure the underlying reader is fully consumed before the writer finalizes the footer.
Example fix
// before fi, _ := os.Stat(path) hdr, _ := tar.FileInfoHeader(fi, "") hdr.Size = 100 // wrong, file is larger tw.WriteHeader(hdr) io.Copy(tw, f) // throws ErrWriteTooLong // after fi, _ := os.Stat(path) hdr, _ := tar.FileInfoHeader(fi, "") hdr.Size = fi.Size() // exact tw.WriteHeader(hdr) io.Copy(tw, f)
Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(path)
if err != nil { return err }
hdr, _ := tar.FileInfoHeader(fi, "")
hdr.Size = fi.Size() // exact, taken at write time Try / catch
n, err := tw.Write(buf)
if errors.Is(err, tar.ErrWriteTooLong) {
log.Printf("truncating entry to declared size: dropped %d bytes", len(buf)-n)
err = nil
} Prevention
- Always set Header.Size from a fresh os.Stat immediately before WriteHeader.
- Use io.CopyN(tw, src, hdr.Size) to bound writes to the declared size.
- Avoid archiving files that may grow concurrently (logs); snapshot or freeze first.
When it happens
Trigger: Calling Write([]byte) with total bytes exceeding the Size set on the prior WriteHeader; using io.Copy from a source whose Length is larger than Header.Size; closing the archive when extra bytes remain past the last entry (ensureEOF check).
Common situations: Setting Header.Size to a smaller value than the actual file (stale stat, race with file growing between os.Stat and io.Copy); copying a growing log file; mismatched Size between WriteHeader and the data stream; concatenating tars incorrectly so Close sees extra bytes.
Related errors
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/c9087e646af0cab6.
Report an issue: GitHub.