golang/go · error
lzw: invalid code
Error message
lzw: invalid code
What it means
The LZW decoder hit its default switch branch, meaning the code read from the stream did not correspond to any defined literal or dictionary entry for the current decoder state. The reader sets r.err and stops decoding; further Reads return the same error.
Source
Thrown at src/compress/lzw/reader.go:198
r.output[i] = uint8(c)
i--
c = r.last
}
// Copy the suffix chain into output and then write that to w.
for c >= r.clear {
r.output[i] = r.suffix[c]
i--
c = r.prefix[c]
}
r.output[i] = uint8(c)
r.o += copy(r.output[r.o:], r.output[i:])
if r.last != decoderInvalidCode {
// Save what the hi code expands to.
r.suffix[r.hi] = uint8(c)
r.prefix[r.hi] = r.last
}
default:
r.err = errors.New("lzw: invalid code")
break loop
}
r.last, r.hi = code, r.hi+1
if r.hi >= r.overflow {
if r.hi > r.overflow {
panic("unreachable")
}
if r.width == maxWidth {
r.last = decoderInvalidCode
// Undo the d.hi++ a few lines above, so that (1) we maintain
// the invariant that d.hi < d.overflow, and (2) d.hi does not
// eventually overflow a uint16.
r.hi--
} else {
r.width++
r.overflow = 1 << r.width
}
}View on GitHub (pinned to b6b368adc5)
Solutions
- Verify the Order (LSB vs MSB) matches the producer: GIF uses LSB, PDF uses MSB.
- Verify the litWidth matches: GIF mandates 2..8 (typically 8 for full-color), PDF typically 8.
- Re-encode or re-transmit the source; this error almost always indicates corruption rather than recoverable input.
- If you control the producer, ensure it emits a clear code and respects the width-bump invariants described in the spec the consumer implements.
Example fix
// before: wrong order for a PDF LZW stream r := lzw.NewReader(src, lzw.LSB, 8) // GIF order on PDF data // after: match the format's bit order r := lzw.NewReader(src, lzw.MSB, 8) // PDF uses MSB defer r.Close()
Defensive patterns
Strategy: try-catch
Validate before calling
// No purely static validation: correctness depends on encoder/decoder agreement. // Document the contract instead: // - GIF LZW: lzw.LSB, litWidth per GIF spec (typically 8) // - PDF LZW: lzw.MSB, litWidth per /BitsPerComponent (typically 8) // Validate the order/litWidth pair against the format spec before constructing.
Try / catch
n, err := r.Read(buf)
if err != nil && err.Error() == "lzw: invalid code" {
// The stream is corrupt or order/litWidth mismatch.
// Re-encode the source or re-fetch a known-good copy.
return corruptLZWStream{cause: err}
} Prevention
- Pin the order and litWidth to the format spec at construction time.
- Round-trip test your encoder against the decoder before shipping.
- Verify bit order in code review — LSB vs MSB is the #1 LZW bug.
When it happens
Trigger: Calling Read on an lzw.Reader fed a malformed compressed stream — codes that exceed the current dictionary width, point at not-yet-defined entries, or appear after the decoder has hit its overflow handling. Typical when the producer and consumer disagree on litWidth or bit order.
Common situations: Decoding a GIF whose LZW stream was truncated, decoding a PDF ASCII85/LZW stream with the wrong EndOfInformation handling, mismatched LSB/MSB order between encoder and decoder, litWidth mismatch (decoder built with litWidth=8 but encoder used 7), or bit-rot in a binary payload.
Related errors
- gzip.ErrChecksum
- zlib.ErrChecksum
- lzw: reader/writer is closed
- lzw: unknown order
- lzw: input byte too large for the litWidth
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/e8680655bbc0be6b.
Report an issue: GitHub.