{"record":{"id":"23ef338c916ca7e2","repo":"golang/go","slug":"flate-closed-writer","errorCode":null,"errorMessage":"flate: closed writer","messagePattern":"flate: closed writer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/compress/flate/deflate.go","lineNumber":783,"sourceCode":"\t}\n\tif d.compressionLevel.chain == 0 {\n\t\treturn\n\t}\n\ts := d.state\n\ts.chainHead = -1\n\tclear(s.hashHead[:])\n\tclear(s.hashPrev[:])\n\ts.hashOffset = 1\n\ts.index = 0\n\td.blockStart, d.byteAvailable = 0, false\n\td.tokens.Reset()\n\ts.length = minMatchLength - 1\n\ts.offset = 0\n\ts.literalCounter = 0\n\ts.maxInsertIndex = 0\n}\n\nvar errWriterClosed = errors.New(\"flate: closed writer\")\n\n// close flushes any uncompressed data and writes an EOF block.\nfunc (d *compressor) close() error {\n\tif d.err == errWriterClosed {\n\t\treturn nil\n\t}\n\tif d.err != nil {\n\t\treturn d.err\n\t}\n\td.sync = true\n\td.step(d)\n\tif d.err != nil {\n\t\treturn d.err\n\t}\n\tif d.w.writeStoredHeader(0, true); d.w.err != nil {\n\t\treturn d.w.err\n\t}\n\td.w.flush()","sourceCodeStart":765,"sourceCodeEnd":801,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/compress/flate/deflate.go#L765-L801","documentation":"errWriterClosed is the sentinel set on the compressor after a successful close() (which flushes, writes the EOF stored block, and detaches the writer via d.w.reset(nil)). Any subsequent Write, Flush, or write-after-close observes d.err != nil and returns it. close() itself is idempotent: a second Close returns nil immediately, so the error surfaces specifically on writes to an already-closed Writer, not on duplicate closes.","triggerScenarios":"Calling Write (or Flush) on a *flate.Writer / *flate.Compressor after Close has succeeded. compressor.write and syncFlush both check `d.err != nil` at the top and short-circuit returning d.err, which is errWriterClosed.","commonSituations":"A defer that writes after the explicit Close; a goroutine that does not observe the close; wrapping a flate.Writer in another writer whose Close does not prevent further writes; misuse of Reset on a closed writer without re-initializing. Common in streaming/HTTP handlers that close the response then continue writing.","solutions":["Stop writing to the Writer after Close; treat Close as terminal for that instance.","If you need to compress again, create a new Writer (or use Reset to re-initialize a reusable compressor with a fresh underlying writer).","Guard writes with a closed flag or ensure Close is the last operation (e.g. via a single owner goroutine).","Use errors.Is(err, flate's closed sentinel) where exposed, or check the closed flag you own, to distinguish this from a real I/O error."],"exampleFix":"// before\nw, _ := flate.NewWriter(buf, flate.DefaultCompression)\nw.Write(data)\nw.Close()\nw.Write(more) // -> flate: closed writer\n\n// after: reuse via Reset for the next stream\nw, _ := flate.NewWriter(buf, flate.DefaultCompression)\nw.Write(data)\nw.Close()\nw.Reset(newBuf) // re-initialize onto a fresh writer\nw.Write(more)\nw.Close()","handlingStrategy":"validation","validationCode":"// Guard against writing to a closed flate.Writer.\ntype safeFlate struct {\n    w *flate.Writer\n    closed bool\n}\nfunc (s *safeFlate) Write(p []byte) (int, error) {\n    if s.closed { return 0, errors.New(\"flate: closed writer\") }\n    return s.w.Write(p)\n}\nfunc (s *safeFlate) Close() error {\n    if s.closed { return nil }\n    s.closed = true\n    return s.w.Close()\n}","typeGuard":"// flate does not export the sentinel; match by string or keep your own closed flag.\nfunc isClosedWriter(err error) bool {\n    return err != nil && err.Error() == \"flate: closed writer\"\n}","tryCatchPattern":"if _, err := w.Write(p); err != nil {\n    if err.Error() == \"flate: closed writer\" {\n        // reopen via Reset or a new Writer and retry once\n    }\n}","preventionTips":["Treat Close as terminal; never write afterward.","Use Reset to reuse a compressor for a new stream rather than reusing a closed one.","Single-owner the Writer so no goroutine writes post-close."],"tags":["flate","compress","writer","closed-resource","stdlib"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}