benbjohnson/litestream · error
open ltx file: %w
Error message
open ltx file: %w
What it means
applyLTXFile's OpenLTXFile call on the replica failed for a reason other than not-exists. The backend could not serve the LTX file identified by level/min/max TXID — connectivity, credentials, or corrupted object metadata.
Source
Thrown at replica.go:949
}
currentTXID = bridgedTXID
}
return currentTXID, nil
}
// applyLTXFile applies a single LTX file's pages to the database file.
// This follows the same pattern as Hydrator.ApplyLTX (vfs.go:712-747).
//
// To prevent concurrent SQLite readers from seeing partial updates, we acquire
// an exclusive file lock before writing. We also rewrite the SQLite header
// (bytes 18-19) to indicate DELETE journal mode instead of WAL mode, and
// randomize the schema change counter (bytes 24-27) to invalidate cached
// schemas in other connections.
func (r *Replica) applyLTXFile(ctx context.Context, f *os.File, info *ltx.FileInfo, pageSize uint32) error {
rc, err := r.Client.OpenLTXFile(ctx, info.Level, info.MinTXID, info.MaxTXID, 0, 0)
if err != nil {
return fmt.Errorf("open ltx file: %w", err)
}
defer rc.Close()
dec := ltx.NewDecoder(rc)
if err := dec.DecodeHeader(); err != nil {
return fmt.Errorf("decode header: %w", err)
}
hdr := dec.Header()
if err := internal.LockFileExclusive(f); err != nil {
return fmt.Errorf("acquire exclusive lock: %w", err)
}
defer internal.UnlockFile(f)
for {
var phdr ltx.PageHeader
data := make([]byte, pageSize)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check backend connectivity and read permissions
- Verify the LTX file exists (litestream ltx <level>)
- Follow mode retries applying the same file on the next poll
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at replica.go:949 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/85cfd56a6e2e369e.
Report an issue: GitHub.