benbjohnson/litestream · error
close ltx encoder: %w
Error message
close ltx encoder: %w
What it means
The LTX encoder failed to close for a non-disk-full reason. enc.Close() flushes buffered page data and writes the LTX trailer with checksums; an I/O or encoding failure here means the staged LTX is incomplete and unusable, so the temp file is removed and the transaction not replicated.
Source
Thrown at db.go:2206
})
if err := db.writeLTXFromWAL(ctx, enc, walFile, info.prevCommit, commit, pageMap); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-write", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("write ltx from wal: %w", err)
}
}
// Encode final trailer to the end of the LTX file.
db.setSyncDiagPhase(diagPhaseCloseLTX, func(s *diagState) {
s.txID = txID
s.walSize = sz
})
if err := enc.Close(); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-write", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
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)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check dmesg/journalctl for block-device errors; run fsck or migrate off failing hardware.
- Move the staging/data directory to reliable local disk (avoid NFS for litestream state).
- Retry replication; transient flush failures usually clear on the next sync.
- Use `litestream reset` if the database's local LTX state is corrupted after repeated failures.
- Keep litestream and its ltx dependency versions matched (rebuild from a single release).
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight storage reliability check on staging volume: // dmesg | grep -iE 'i/o error|blk_update' || echo "storage clean"
Try / catch
if err != nil && strings.Contains(err.Error(), "close ltx encoder") {
log.Printf("LTX finalize failed (flush/trailer): %v — staged file discarded, next sync retries", err)
if recurring(err) { /* litestream reset */ }
} Prevention
- Use reliable local disk for litestream state (avoid NFS)
- Monitor storage errors via SMART/dmesg
- Keep litestream and ltx dependency versions aligned
- Treat repeated close failures as a reset+resnapshot trigger
When it happens
Trigger: Flush/trailer write I/O error on the temp file (bad block, fd invalidated mid-write, storage error), or an internal ltx encoder state error (e.g. encode called on a writer that already failed).
Common situations: Failing or flaky storage on the staging volume; container storage-layer errors; NFS interruptions; a previously swallowed write error surfacing at Close flush time.
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
- encode ltx header: %w
- write ltx from db: %w
- write ltx from wal: %w
- open temp ltx file: %w
- new ltx encoder: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/dcfca9570c18469f.
Report an issue: GitHub.