{"record":{"id":"4665655152340590","repo":"golang/go","slug":"decompressor-already-registered","errorCode":null,"errorMessage":"decompressor already registered","messagePattern":"decompressor already registered","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/archive/zip/register.go","lineNumber":121,"sourceCode":"\nvar (\n\tcompressors   sync.Map // map[uint16]Compressor\n\tdecompressors sync.Map // map[uint16]Decompressor\n)\n\nfunc init() {\n\tcompressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))\n\tcompressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))\n\n\tdecompressors.Store(Store, Decompressor(io.NopCloser))\n\tdecompressors.Store(Deflate, Decompressor(newFlateReader))\n}\n\n// RegisterDecompressor allows custom decompressors for a specified method ID.\n// The common methods [Store] and [Deflate] are built in.\nfunc RegisterDecompressor(method uint16, dcomp Decompressor) {\n\tif _, dup := decompressors.LoadOrStore(method, dcomp); dup {\n\t\tpanic(\"decompressor already registered\")\n\t}\n}\n\n// RegisterCompressor registers custom compressors for a specified method ID.\n// The common methods [Store] and [Deflate] are built in.\nfunc RegisterCompressor(method uint16, comp Compressor) {\n\tif _, dup := compressors.LoadOrStore(method, comp); dup {\n\t\tpanic(\"compressor already registered\")\n\t}\n}\n\nfunc compressor(method uint16) Compressor {\n\tci, ok := compressors.Load(method)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn ci.(Compressor)\n}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/archive/zip/register.go#L103-L139","documentation":"`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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only register non-built-in methods once, early in main or a single package init.","Avoid re-registering `zip.Store` (0) and `zip.Deflate` (8).","Guard with a sentinel (e.g. a `sync.Once` or a package-level bool) if registration may be reached from multiple paths."],"exampleFix":"// before\nfunc init() {\n    zip.RegisterDecompressor(12, bzip2Reader) // panics if loaded twice\n}\n// after\nvar registerOnce sync.Once\nfunc ensureBzip2() {\n    registerOnce.Do(func() { zip.RegisterDecompressor(12, bzip2Reader) })\n}","handlingStrategy":"validation","validationCode":"var regDec sync.Once\nregDec.Do(func() { zip.RegisterDecompressor(12, newBzip2Reader) })","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never re-register zip.Store or zip.Deflate.","Centralize all codec registration in a single package imported once."],"tags":["archive","zip","panic","registration","global-state"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}