benbjohnson/litestream · error
_litestream_lock: %w
Error message
_litestream_lock: %w
What it means
Inside the passive-checkpoint barrier transaction, Litestream inserts into its internal _litestream_lock table to serialize against other sync activity. This error wraps the failure of that INSERT, aborting the passive checkpoint.
Source
Thrown at db.go:2504
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)
}
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,View on GitHub (pinned to 4ed7a308f6)
Solutions
- Restart Litestream so it re-creates its internal schema on the database
- Verify the table exists: `sqlite3 app.db '.tables' | grep _litestream_lock`
- Check for competing write locks or a read-only filesystem/mount
- Check disk space and database file permissions
Example fix
// before sqlite3 app.db 'DROP TABLE _litestream_lock;' # someone cleaned up tables // after systemctl restart litestream # recreates internal tables sqlite3 app.db '.tables' | grep _litestream_lock
Defensive patterns
Strategy: try-catch
Validate before calling
// confirm litestream's internal schema exists
rows, _ := db.Query("SELECT count(*) FROM sqlite_master WHERE name='_litestream_lock'")
// count==0 => litestream has not initialized this database Try / catch
// go
if err := checkpoint(ctx, CheckpointModePassive); err != nil {
if strings.Contains(err.Error(), "_litestream_lock") {
// schema missing or locked: restart litestream to re-init; check read-only fs
}
} Prevention
- Never drop litestream's internal tables
- Restart litestream after restoring/replacing a database file
- Ensure the DB mount is writable and has free space
- Don't run other tools that take exclusive locks during checkpoints
When it happens
Trigger: In checkpointWithExecutor (passive mode) when barrierTx.ExecContext(ctx, `INSERT INTO _litestream_lock (id) VALUES (1);`) fails — table missing (fresh/restored DB before Litestream initialized its schema), database locked, or disk I/O error.
Common situations: The _litestream_lock table was dropped or the DB was replaced/restored without Litestream re-initializing, a foreign process holds a write lock, or the filesystem is read-only/full.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/70c31d97300814f4.
Report an issue: GitHub.