benbjohnson/litestream · error
close ltx file: %w
Error message
close ltx file: %w
What it means
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.
Source
Thrown at db.go:2224
return result, fmt.Errorf("close ltx encoder: %w", err)
}
// Sync & close LTX file.
db.setSyncDiagPhase(diagPhaseFsyncLTX, func(s *diagState) {
s.txID = txID
s.walSize = sz
})
if err := ltxFile.Sync(); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-sync", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("sync ltx file: %w", err)
}
if err := ltxFile.Close(); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-close", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("close ltx file: %w", err)
}
// Atomically rename file to final path.
db.setSyncDiagPhase(diagPhaseRenameLTX, func(s *diagState) {
s.txID = txID
s.walSize = sz
})
if err := os.Rename(tmpFilename, filename); err != nil {
db.maxLTXFileInfos.Lock()
delete(db.maxLTXFileInfos.m, 0) // clear cache if in unknown state
db.maxLTXFileInfos.Unlock()
db.invalidatePosCache()
return result, fmt.Errorf("rename ltx file: %w", err)
}
if err := internal.FsyncDir(filepath.Dir(filename)); err != nil {
db.maxLTXFileInfos.Lock()
delete(db.maxLTXFileInfos.m, 0) // clear cache if in unknown state
db.maxLTXFileInfos.Unlock()View on GitHub (pinned to 4ed7a308f6)
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.
Defensive patterns
Strategy: try-catch
Type guard
func isLTXStageErr(err error) (stage string, ok bool) {
var e *LTXError
if errors.As(err, &e) { return e.Stage, true }
return "", false
} Try / catch
if err := db.Sync(ctx); err != nil {
if strings.Contains(err.Error(), "close ltx file") {
// check device health; restart process if repeated
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/e3f8f5395e7ec018.
Report an issue: GitHub.