golang/go · critical

decompressor already registered

Error message

decompressor already registered

What it means

`zip.RegisterDecompressor(method, dcomp)` installs a custom decompressor for a given zip method ID; it panics if a decompressor for that method is already registered. The package's `init` pre-registers Store(0) and Deflate(8), so re-registering either panics. Registration is global (a `sync.Map` shared process-wide).

Source

Thrown at src/archive/zip/register.go:121

var (
	compressors   sync.Map // map[uint16]Compressor
	decompressors sync.Map // map[uint16]Decompressor
)

func init() {
	compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
	compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))

	decompressors.Store(Store, Decompressor(io.NopCloser))
	decompressors.Store(Deflate, Decompressor(newFlateReader))
}

// RegisterDecompressor allows custom decompressors for a specified method ID.
// The common methods [Store] and [Deflate] are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
	if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
		panic("decompressor already registered")
	}
}

// RegisterCompressor registers custom compressors for a specified method ID.
// The common methods [Store] and [Deflate] are built in.
func RegisterCompressor(method uint16, comp Compressor) {
	if _, dup := compressors.LoadOrStore(method, comp); dup {
		panic("compressor already registered")
	}
}

func compressor(method uint16) Compressor {
	ci, ok := compressors.Load(method)
	if !ok {
		return nil
	}
	return ci.(Compressor)
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Only register non-built-in methods once, early in main or a single package init.
  2. Avoid re-registering `zip.Store` (0) and `zip.Deflate` (8).
  3. Guard with a sentinel (e.g. a `sync.Once` or a package-level bool) if registration may be reached from multiple paths.

Example fix

// before
func init() {
    zip.RegisterDecompressor(12, bzip2Reader) // panics if loaded twice
}
// after
var registerOnce sync.Once
func ensureBzip2() {
    registerOnce.Do(func() { zip.RegisterDecompressor(12, bzip2Reader) })
}
Defensive patterns

Strategy: validation

Validate before calling

var regDec sync.Once
regDec.Do(func() { zip.RegisterDecompressor(12, newBzip2Reader) })

Prevention

When it happens

Trigger: Calling `RegisterDecompressor(zip.Store, ...)` or `RegisterDecompressor(zip.Deflate, ...)` — both already registered at init; calling your custom registration twice in the same binary; a library and its test both registering the same method; an `init()` ordering issue causing a duplicate.

Common situations: A third-party zip codec library's `init` colliding with your own; tests that re-register on each run; a plugin/host both registering BZIP2/ZIP method 12.

Related errors


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