benbjohnson/litestream · error
cannot seal wal before passive checkpoint: %w
Error message
cannot seal wal before passive checkpoint: %w
What it means
After acquiring the barrier lock in a passive checkpoint, Litestream performs one more sync to seal (fully replicate) the WAL before running the actual PRAGMA wal_checkpoint. This error wraps failure of that sealing sync, and the checkpoint is aborted to guarantee the replica has all WAL data first.
Source
Thrown at db.go:2509
var barrierTx *sql.Tx
if mode == CheckpointModePassive {
barrierTx, err = db.db.BeginTx(ctx, nil)
if err != nil {
return false, fmt.Errorf("begin passive checkpoint barrier: %w", err)
}
defer func() {
if barrierTx != nil {
_ = rollback(barrierTx)
}
}()
if _, err := barrierTx.ExecContext(ctx, `INSERT INTO _litestream_lock (id) VALUES (1);`); err != nil {
return false, fmt.Errorf("_litestream_lock: %w", err)
}
result, err = db.verifyAndSyncWithExecutor(ctx, true, exec, 0)
if err != nil {
return false, fmt.Errorf("cannot seal wal before passive checkpoint: %w", err)
}
exec.applySyncResult(result)
}
frameSize := int64(db.pageSize + WALFrameHeaderSize)
preCheckpointFrameN := 0
if exec.state.lastSyncedWALOffset > WALHeaderSize {
preCheckpointFrameN = int((exec.state.lastSyncedWALOffset - WALHeaderSize) / frameSize)
}
// Execute checkpoint and immediately issue a write to the WAL to ensure
// a new page is written.
db.setSyncDiagPhase(diagPhaseCheckpointExec,
func(s *diagState) {
s.checkpointMode = mode
s.lastSyncedWALOffset = exec.state.lastSyncedWALOffset
})
walFrameN, err := db.execCheckpoint(ctx, mode)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Inspect the wrapped inner error and fix the underlying sync failure (storage creds, network, disk)
- Retry the checkpoint after storage is reachable
- Run `litestream reset` only if local LTX state is confirmed corrupt
- Monitor replica storage health; consider `auto-recover: true` cautiously per docs
Example fix
// before litestream ltx ... # cannot seal wal before passive checkpoint: context deadline exceeded // after # raise storage timeout / fix network, then retry litestream ltx -db /var/lib/db/app.db
Defensive patterns
Strategy: retry
Validate before calling
// verify storage is reachable before running passive checkpoints
if err := storageHealthCheck(ctx); err != nil { log.Printf("skip checkpoint: %v", err) } Try / catch
// go
if err := checkpoint(ctx, CheckpointModePassive); err != nil {
if strings.Contains(err.Error(), "cannot seal wal before passive checkpoint") {
// inspect wrapped sync error (network, creds, disk) and retry after remediation
}
} Prevention
- Monitor replica storage availability and token expiry
- Keep sufficient disk headroom for LTX writes
- Schedule maintenance checkpoints outside network-sensitive windows
- Investigate recurring WAL sync failures — they surface here first
When it happens
Trigger: In checkpointWithExecutor (passive mode) when db.verifyAndSyncWithExecutor(ctx, true, exec, 0) fails after the _litestream_lock insert — same causes as pre-checkpoint copy: storage failures, WAL read/encode errors, or client I/O errors.
Common situations: Object storage outages or expired credentials mid-checkpoint, disk full during LTX write, corrupt WAL page producing an encode error, or transient network failures.
Related errors
- cannot copy wal before checkpoint: %w
- cannot copy wal after passive checkpoint: %w
- cannot copy wal after checkpoint: %w
- cannot snapshot after checkpoint: %w
- checkpoint: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/f647d59a767a3170.
Report an issue: GitHub.