golang/go · error

gzip.Write: Extra data is too large

Error message

gzip.Write: Extra data is too large

What it means

gzip.Writer.writeBytes rejects any byte slice longer than 0xffff (65535) because the GZIP FEXTRA field stores its length in a 2-byte little-endian XLEN prefix. writeBytes is used internally when emitting the Header.Extra bytes during the next Write/Flush call, so the error propagates from those methods.

Source

Thrown at src/compress/gzip/gzip.go:103

		},
		w:          w,
		level:      level,
		compressor: compressor,
	}
}

// Reset discards the [Writer] z's state and makes it equivalent to the
// result of its original state from [NewWriter] or [NewWriterLevel], but
// writing to w instead. This permits reusing a [Writer] rather than
// allocating a new one.
func (z *Writer) Reset(w io.Writer) {
	z.init(w, z.level)
}

// writeBytes writes a length-prefixed byte slice to z.w.
func (z *Writer) writeBytes(b []byte) error {
	if len(b) > 0xffff {
		return errors.New("gzip.Write: Extra data is too large")
	}
	le.PutUint16(z.buf[:2], uint16(len(b)))
	_, err := z.w.Write(z.buf[:2])
	if err != nil {
		return err
	}
	_, err = z.w.Write(b)
	return err
}

// writeString writes a UTF-8 string s in GZIP's format to z.w.
// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
func (z *Writer) writeString(s string) (err error) {
	// GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
	needconv := false
	for _, v := range s {
		if v == 0 || v > 0xff {
			return errors.New("gzip.Write: non-Latin-1 header string")

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Trim or chunk the Extra payload so len(Header.Extra) <= 65535 bytes.
  2. Move the oversized metadata out of the GZIP header into a sidecar file or a separate framing layer.
  3. If you need arbitrary-length metadata, define your own container format that wraps the gzip stream rather than abusing FEXTRA.
  4. Validate the length once when assigning Header.Extra rather than discovering the error on every Write.

Example fix

// before
gz.Header.Extra = bigMetadataBlob // > 64 KiB
// "gzip.Write: Extra data is too large"

// after: cap and spill
const maxExtra = 0xffff
if len(bigMetadataBlob) > maxExtra {
    return fmt.Errorf("metadata %d bytes exceeds gzip FEXTRA limit %d",
        len(bigMetadataBlob), maxExtra)
}
gz.Header.Extra = bigMetadataBlob
Defensive patterns

Strategy: validation

Validate before calling

const gzipMaxExtra = 0xffff

func setExtra(h *gzip.Header, extra []byte) error {
    if len(extra) > gzipMaxExtra {
        return fmt.Errorf("extra field %d bytes exceeds %d", len(extra), gzipMaxExtra)
    }
    h.Extra = extra
    return nil
}

Try / catch

gz.Header.Extra = blob
if _, err := gz.Write(nil); err != nil { // or first Write
    if strings.Contains(err.Error(), "Extra data is too large") {
        return oversizeExtraError{len: len(blob)}
    }
}

Prevention

When it happens

Trigger: Setting gz.Header.Extra (or passing Extra via the Writer zero-value before Reset) to a slice whose length exceeds 65535, then calling Write, Flush, or Close on the writer. The check fires before any byte is written to the underlying writer.

Common situations: Embedding a metadata blob, JSON manifest, signing payload, or trace context in the GZIP extra field and exceeding the 64 KiB ceiling; copying Extra from a different format that has no such limit; appending authentication tags without bound.

Related errors


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