{"record":{"id":"71c7f3e9085fd343","repo":"hyperledger/fabric","slug":"error-while-closing-the-snapshot-file-s-71c7f3","errorCode":null,"errorMessage":"error while closing the snapshot file: %s","messagePattern":"error while closing the snapshot file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"common/ledger/snapshot/file.go","lineNumber":119,"sourceCode":"\tif err := c.bufWriter.Flush(); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"error while flushing to the snapshot file: %s \", c.file.Name())\n\t}\n\tif err := c.file.Sync(); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := c.file.Close(); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"error while closing the snapshot file: %s \", c.file.Name())\n\t}\n\treturn c.hasher.Sum(nil), nil\n}\n\n// Close closes the underlying file, if not already done. A consumer can invoke this function if the consumer\n// encountered some error and simply wants to abandon the snapshot file creation (typically, intended to be used in a defer statement)\nfunc (c *FileWriter) Close() error {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn errors.Wrapf(c.file.Close(), \"error while closing the snapshot file: %s\", c.file.Name())\n}\n\n// FileReader reads from a ledger snapshot file. This is expected to be used for loading the ledger snapshot data\n// during bootstrapping a channel from snapshot. The data should be read, using the functions `DecodeXXX`,\n// in the same sequence in which the data was written by the functions `EncodeXXX` in the `FileCreator`.\n// Note that the FileReader does not verify the hash of stream and it is expected that the hash has been verified\n// by the consumer. Later, if we decide to perform this, on-the-side, while loading the snapshot data, the FileRedear,\n// like the FileCreator, would take a `hasher` as an input\ntype FileReader struct {\n\tfile              *os.File\n\tbufReader         *bufio.Reader\n\treusableByteSlice []byte\n}\n\n// OpenFile constructs a FileReader. This function returns an error if the format of the file, stored in the\n// first byte, does not match with the expectedDataFormat\nfunc OpenFile(filePath string, expectDataformat byte) (*FileReader, error) {\n\tfile, err := os.Open(filePath)","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/snapshot/file.go#L101-L137","documentation":"Close abandons the snapshot file (typically in a defer after an error) by closing the underlying file; the result of file.Close() is wrapped with this message. It can also wrap a double-close error if Done already closed the file — but note Close() returns nil when the receiver itself is nil. A non-nil return means the file descriptor could not be closed cleanly.","triggerScenarios":"Calling Close() after Done() already closed the file (yields 'file already closed' wrapped error), or Close() when the underlying close(2) syscall fails.","commonSituations":"defer w.Close() running after a successful Done(); duplicated cleanup in error paths; OS-level close errors on network mounts.","solutions":["Only call Close() on the error/abandon path; rely on Done() to close on success","Guard cleanup with a flag so Close isn't invoked after Done","Ignore or log the wrapped 'file already closed' error in deferred cleanup if Done succeeded"],"exampleFix":"// before\ndefer w.Close()\nhash, err := w.Done()\n// after\nhash, err := w.Done()\nif err != nil {\n    defer w.Close() // close only on failure\n}","handlingStrategy":"try-catch","validationCode":"// guard: skip Close if Done already finalized\nif done { return nil }","typeGuard":null,"tryCatchPattern":"if cerr := w.Close(); cerr != nil && !strings.Contains(cerr.Error(), \"already closed\") {\n    log.Warnf(\"snapshot cleanup: %v\", cerr)\n}","preventionTips":["Structure cleanup so Close runs only when Done failed or was not reached","Ignore benign 'file already closed' errors in deferred cleanup","Close is nil-receiver safe, but not double-call safe"],"tags":["io","snapshot","close","resource-leak"],"backgroundTag":"file-already-closed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}