benbjohnson/litestream · error
begin passive checkpoint barrier: %w
Error message
begin passive checkpoint barrier: %w
What it means
For passive checkpoints, Litestream opens a barrier transaction (BeginTx) on the SQLite database to hold a read lock during the checkpoint. This error wraps a failure to begin that transaction, so the passive checkpoint cannot proceed safely.
Source
Thrown at db.go:2495
}
// Copy end of WAL before checkpoint to copy as much as possible.
db.setSyncDiagPhase(diagPhaseCheckpointCopyBefore,
func(s *diagState) {
s.checkpointMode = mode
s.lastSyncedWALOffset = exec.state.lastSyncedWALOffset
})
result, err := db.verifyAndSyncWithExecutor(ctx, true, exec, 0)
if err != nil {
return false, fmt.Errorf("cannot copy wal before checkpoint: %w", err)
}
exec.applySyncResult(result)
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)
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Identify blocking writers (`PRAGMA busy_timeout;`, `sqlite3 app.db '.timeout'` or lsof on the db) and let them finish
- Increase the busy timeout / reduce long-running write transactions in the application
- Avoid forcing checkpoints during application write bursts; rely on the normal checkpoint cadence
- Retry after the lock clears — the error is typically transient
Example fix
// before app: single long transaction holding write lock for minutes litestream: begin passive checkpoint barrier: database is locked // after -- break long transactions into smaller commits -- and/or set busy_timeout PRAGMA busy_timeout = 5000;
Defensive patterns
Strategy: try-catch
Validate before calling
// avoid forcing passive checkpoints while heavy writers run
if longWriteTxActive(app) { log.Printf("defer checkpoint") } Try / catch
// go
if err := checkpoint(ctx, CheckpointModePassive); err != nil {
if strings.Contains(err.Error(), "begin passive checkpoint barrier") {
// database locked/closed: retry with backoff; check for blocking writers
}
} Prevention
- Keep application write transactions short
- Set a reasonable busy_timeout in SQLite
- Don't force checkpoints during peak write load or shutdown
- Only one checkpoint coordinator per database
When it happens
Trigger: In checkpointWithExecutor, mode == CheckpointModePassive, when db.db.BeginTx(ctx, nil) returns an error — database locked beyond busy timeout, database closed, or context canceled.
Common situations: Another process holds a long write transaction (locking the DB), the database is in a locking dispute with other tooling, or Litestream is shutting down (context canceled) when the checkpoint fires.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- rollback passive checkpoint barrier: %w
- begin: %w
- rollback post-checkpoint tx: %w
- begin transaction: %w
- commit transaction: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/bed8f96070dfd82c.
Report an issue: GitHub.