{"record":{"id":"e3f8f5395e7ec018","repo":"benbjohnson/litestream","slug":"close-ltx-file-w","errorCode":null,"errorMessage":"close ltx file: %w","messagePattern":"close ltx file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":2224,"sourceCode":"\t\treturn result, fmt.Errorf(\"close ltx encoder: %w\", err)\n\t}\n\n\t// Sync & close LTX file.\n\tdb.setSyncDiagPhase(diagPhaseFsyncLTX, func(s *diagState) {\n\t\ts.txID = txID\n\t\ts.walSize = sz\n\t})\n\tif err := ltxFile.Sync(); err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-sync\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, fmt.Errorf(\"sync ltx file: %w\", err)\n\t}\n\tif err := ltxFile.Close(); err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-close\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, fmt.Errorf(\"close ltx file: %w\", err)\n\t}\n\n\t// Atomically rename file to final path.\n\tdb.setSyncDiagPhase(diagPhaseRenameLTX, func(s *diagState) {\n\t\ts.txID = txID\n\t\ts.walSize = sz\n\t})\n\tif err := os.Rename(tmpFilename, filename); err != nil {\n\t\tdb.maxLTXFileInfos.Lock()\n\t\tdelete(db.maxLTXFileInfos.m, 0) // clear cache if in unknown state\n\t\tdb.maxLTXFileInfos.Unlock()\n\t\tdb.invalidatePosCache()\n\t\treturn result, fmt.Errorf(\"rename ltx file: %w\", err)\n\t}\n\tif err := internal.FsyncDir(filepath.Dir(filename)); err != nil {\n\t\tdb.maxLTXFileInfos.Lock()\n\t\tdelete(db.maxLTXFileInfos.m, 0) // clear cache if in unknown state\n\t\tdb.maxLTXFileInfos.Unlock()","sourceCodeStart":2206,"sourceCodeEnd":2242,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L2206-L2242","documentation":"Closing the temporary LTX file failed with a non-disk-full error. Litestream wraps it as 'close ltx file:' because the file descriptor could not be released/flushed cleanly. The LTX transaction is abandoned and the temp file may remain on disk.","triggerScenarios":"ltxFile.Close() at db.go:2220 returned an error such as EIO (failing storage), EBADF (internal descriptor state), or a network-filesystem flush error not matching isDiskFullError.","commonSituations":"Hardware I/O failures; NFS/EFS sessions dropped mid-write; fd leaks elsewhere in the process exhausting descriptors indirectly; storage backend errors on container volumes.","solutions":["Read the wrapped OS error and check system logs (dmesg) for device failures.","Remove the orphaned temp LTX file and retry the sync.","If EBADF or repeated failures occur, restart the litestream process to reset descriptor state.","Move to local storage or replace failing hardware."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isLTXStageErr(err error) (stage string, ok bool) {\n\tvar e *LTXError\n\tif errors.As(err, &e) { return e.Stage, true }\n\treturn \"\", false\n}","tryCatchPattern":"if err := db.Sync(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"close ltx file\") {\n\t\t// check device health; restart process if repeated\n\t}\n\treturn err\n}","preventionTips":["Use reliable local storage; avoid flaky network filesystems.","Restart litestream if repeated close errors suggest fd/state issues.","Remove orphaned temp files after failures.","Keep kernel and storage drivers current."],"tags":["close","io-error","filesystem"],"backgroundTag":"file-write-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}