golang/go · error

lzw: unknown order

Error message

lzw: unknown order

What it means

Reader.init switches on the Order argument and only accepts lzw.LSB and lzw.MSB. Any other value lands in the default branch, sets r.err to "lzw: unknown order", and returns without initializing the bit reader. The same Reader can later be repaired via Reset with a valid Order.

Source

Thrown at src/compress/lzw/reader.go:271

// is a *[Reader].
func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
	return newReader(r, order, litWidth)
}

func newReader(src io.Reader, order Order, litWidth int) *Reader {
	r := new(Reader)
	r.init(src, order, litWidth)
	return r
}

func (r *Reader) init(src io.Reader, order Order, litWidth int) {
	switch order {
	case LSB:
		r.read = (*Reader).readLSB
	case MSB:
		r.read = (*Reader).readMSB
	default:
		r.err = errors.New("lzw: unknown order")
		return
	}
	if litWidth < 2 || 8 < litWidth {
		r.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
		return
	}

	br, ok := src.(io.ByteReader)
	if !ok && src != nil {
		br = bufio.NewReader(src)
	}
	r.r = br
	r.litWidth = litWidth
	r.width = 1 + uint(litWidth)
	r.clear = uint16(1) << uint(litWidth)
	r.eof, r.hi = r.clear+1, r.clear+1
	r.overflow = uint16(1) << r.width
	r.last = decoderInvalidCode

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass one of the package constants: lzw.LSB for GIF-style data, lzw.MSB for PDF-style data.
  2. Audit enum-to-Order casts; never cast an arbitrary int to lzw.Order without bounds-checking.
  3. Add a unit test that exercises both orders so a regression is caught at build time.

Example fix

// before
var order lzw.Order // zero value is not a valid Order
r := lzw.NewReader(src, order, 8)

// after: pick explicitly
r := lzw.NewReader(src, lzw.LSB, 8) // for GIF
// or lzw.MSB for PDF
Defensive patterns

Strategy: validation

Validate before calling

func validOrder(o lzw.Order) error {
    switch o {
    case lzw.LSB, lzw.MSB: return nil
    default: return fmt.Errorf("invalid lzw.Order %d", o)
    }
}

func newLZWReader(src io.Reader, order lzw.Order, litWidth int) (*lzw.Reader, error) {
    if err := validOrder(order); err != nil { return nil, err }
    return lzw.NewReader(src, order, litWidth), nil
}

Type guard

func isValidOrder(o lzw.Order) bool {
    return o == lzw.LSB || o == lzw.MSB
}

Try / catch

// lzw.NewReader never returns an error; check the first Read.
if _, err := r.Read(buf); err != nil {
    if err.Error() == "lzw: unknown order" { /* fix the Order argument */ }
}

Prevention

When it happens

Trigger: Calling lzw.NewReader(src, order, litWidth) where order is neither lzw.LSB (0) nor lzw.MSB (1) — typically a zero-value of a custom int type cast to Order, or an out-of-range constant.

Common situations: Calling NewReader with an uninitialized Order variable, or after refactoring where an enum was renamed and the caller still passes the old (now invalid) value.

Related errors


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