{"record":{"id":"8364a8adfc49b442","repo":"rqlite/rqlite","slug":"failed-to-write-decompressed-data-to-file-v","errorCode":null,"errorMessage":"failed to write decompressed data to file: %v","messagePattern":"failed to write decompressed data to file: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"command/chunking/dechunker.go","lineNumber":58,"sourceCode":"\t} else if d.streamID != chunk.StreamId {\n\t\treturn false, fmt.Errorf(\"chunk has unexpected stream ID: expected %s but got %s\", d.streamID, chunk.StreamId)\n\t}\n\n\tif chunk.SequenceNum != d.seqNum+1 {\n\t\treturn false, fmt.Errorf(\"chunks received out of order: expected %d but got %d\", d.seqNum+1, chunk.SequenceNum)\n\t}\n\td.seqNum = chunk.SequenceNum\n\n\tif chunk.Data != nil {\n\t\tbuf := bytes.NewBuffer(chunk.Data)\n\t\tgzw, err := gzip.NewReader(buf)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to create gzip reader: %v\", err)\n\t\t}\n\t\tdefer gzw.Close()\n\n\t\tif _, err := io.Copy(d.file, gzw); err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to write decompressed data to file: %v\", err)\n\t\t}\n\t}\n\n\treturn chunk.IsLast, nil\n}\n\n// Close closes the Dechunker and returns the file path containing the reassembled data.\nfunc (d *Dechunker) Close() (string, error) {\n\tif err := d.file.Close(); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to close file: %v\", err)\n\t}\n\treturn d.filePath, nil\n}\n\n// DechunkerManager manages Dechunkers.\ntype DechunkerManager struct {\n\tdir string\n\tmu  sync.Mutex","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/command/chunking/dechunker.go#L40-L76","documentation":"The Dechunker reassembles gzip-compressed chunks into a single file. This error is wrapped by WriteChunk when io.Copy fails while writing decompressed bytes from the gzip reader into the underlying temp file. It indicates the disk write failed mid-stream, so the reassembled file is incomplete or unwritable.","triggerScenarios":"Calling Dechunker.WriteChunk with a chunk whose decompression succeeds but whose destination file write fails: disk full, I/O error, file descriptor closed/invalid, or underlying storage failure during io.Copy(d.file, gzw).","commonSituations":"Uploading very large compressed blobs (backups, restores) that exceed available disk space on the node's temp/data directory; read-only or full filesystem; container disk quota exceeded mid-transfer.","solutions":["Free disk space on the directory backing the Dechunker (usually the node's data dir) and retry the upload from the first chunk","Check filesystem permissions and mount health (df, dmesg for I/O errors)","Inspect the wrapped inner error (%v) to distinguish ENOSPC from EIO or a closed-file bug","If using containers, verify the volume quota and increase it"],"exampleFix":"// caller before/after: check space before a large chunked upload\n// before\ndechunker.WriteChunk(chunk)\n// after\nif free, _ := diskFree(dataDir); free < expectedSize {\n    return fmt.Errorf(\"insufficient disk space in %s: need ~%d bytes\", dataDir, expectedSize)\n}\nerr := decomposer.Write(rl, dechunkerFn) // then handle error, delete partial file","handlingStrategy":"try-catch","validationCode":"// Go: check free space on the dechunker directory before large transfers\nfunc hasFreeSpace(dir string, need uint64) bool {\n    var st syscall.Statfs_t\n    if err := syscall.Statfs(dir, &st); err != nil { return false }\n    return uint64(st.Bavail)*uint64(st.Bsize) >= need\n}","typeGuard":null,"tryCatchPattern":"if _, err := dechunker.WriteChunk(chunk); err != nil {\n    if strings.Contains(err.Error(), \"failed to write decompressed data\") {\n        // clean up partial temp file, free space or fix fs, restart chunked transfer from chunk 0\n    }\n    return err\n}","preventionTips":["Monitor free space on the node's data directory before chunked uploads/restores","Delete partial reassembly files after a failed transfer","Alert on disk usage thresholds (e.g. 85%) in production","Keep the dechunker temp dir on the same healthy volume as the data dir"],"tags":["disk","io","gzip","chunking"],"backgroundTag":"disk-full-write-failure","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}