benbjohnson/litestream · error
detect full checkpoint: %w
Error message
detect full checkpoint: %w
What it means
When WAL header salts differ from the LTX-recorded salts, verify calls detectFullCheckpoint() to decide whether a full/restart checkpoint rewrote the WAL or whether syncing can continue incrementally. Any error from that detection is wrapped here and aborts the sync cycle.
Source
Thrown at db.go:1809
} else if !lastPageMatch {
info.reason = "last page does not exist in last ltx file, wal overwritten by another process"
return info, nil
}
db.Logger.Debug("verify.2", "lastPageMatch", lastPageMatch)
// Salt has changed which could indicate a FULL checkpoint.
// If we have a last page match, then we can assume that the WAL has not been overwritten.
if !saltMatch {
db.Logger.Log(ctx, internal.LevelTrace, "wal restarted",
"salt1", salt1,
"salt2", salt2)
info.offset = WALHeaderSize
info.salt1, info.salt2 = salt1, salt2
if detected, err := db.detectFullCheckpoint(ctx, [][2]uint32{{salt1, salt2}, {dec.Header().WALSalt1, dec.Header().WALSalt2}}); err != nil {
return info, fmt.Errorf("detect full checkpoint: %w", err)
} else if detected {
info.reason = "full or restart checkpoint detected, snapshotting"
} else {
info.snapshotting = false
}
return info, nil
}
info.snapshotting = false
return info, nil
}
// lastPageMatch checks if the last page read in the WAL exists in the last LTX file.
func (db *DB) lastPageMatch(ctx context.Context, dec *ltx.Decoder, prevWALOffset, frameSize int64) (bool, error) {
if prevWALOffset <= WALHeaderSize {
return false, nilView on GitHub (pinned to 4ed7a308f6)
Solutions
- Look at the wrapped inner error to distinguish WAL read vs LTX decode problems
- If LTX files are corrupt, `litestream reset` and resnapshot
- Reduce conflicting writers; ensure single-process ownership of the DB
- Retry after fixing transient IO conditions
Defensive patterns
Strategy: retry
Try / catch
if err := db.Sync(ctx); err != nil {
if strings.Contains(err.Error(), "detect full checkpoint") {
// transient IO: backoff and retry; corruption: reset
}
} Prevention
- Tune checkpointing so full checkpoints don't storm the WAL
- Maintain single-writer ownership of the database
- Alert on repeated salt-mismatch snapshotting in litestream logs
When it happens
Trigger: Salt mismatch path taken in verifyWithExecutor and detectFullCheckpoint fails — it reads WAL/LTX data to compare page content, so any WAL read or LTX decode error propagates here.
Common situations: Aggressive checkpointing by the application combined with IO errors; corrupted LTX files preventing content comparison; concurrent access to the database by another process.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- checkpoint: %w
- checkpoint failed: %w
- read wal header after expected truncation: %w
- cannot read wal header: %w
- cannot copy wal before checkpoint: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/f80b18a889beaa75.
Report an issue: GitHub.