benbjohnson/litestream · error
cannot snapshot after checkpoint: %w
Error message
cannot snapshot after checkpoint: %w
What it means
While still holding the checkpoint write transaction, Litestream performs a boundary snapshot sync (db.sync with a snapshot WAL read position) to capture everything written up to the checkpoint. Failure of that sync is wrapped with this error and aborts the checkpoint. The replication stream will lack the boundary frames until a later sync succeeds.
Source
Thrown at db.go:2619
return false, fmt.Errorf("_litestream_lock: %w", err)
}
// Copy anything that may have occurred after the checkpoint.
db.setSyncDiagPhase(diagPhaseCheckpointSnapshotBoundary,
func(s *diagState) {
s.checkpointMode = mode
s.lastSyncedWALOffset = exec.state.lastSyncedWALOffset
})
snapshotInfo := syncInfo{
offset: WALHeaderSize,
salt1: binary.BigEndian.Uint32(other[16:]),
salt2: binary.BigEndian.Uint32(other[20:]),
snapshotting: true,
reason: "checkpoint boundary snapshot",
}
result, err = db.sync(ctx, true, exec, snapshotInfo, 0)
if err != nil {
return false, fmt.Errorf("cannot snapshot after checkpoint: %w", err)
}
exec.applySyncResult(result)
// Release write lock before exiting.
// Use rollback() helper for consistency with releaseReadLock() and the
// defer above. See issue #934.
if err := rollback(tx); err != nil {
return false, fmt.Errorf("rollback post-checkpoint tx: %w", err)
}
exec.state.syncedSinceCheckpoint = false
return true, nil
}
// execCheckpoint issues a wal_checkpoint PRAGMA in the given mode and returns
// the number of frames in the WAL as reported by the checkpoint.
func (db *DB) execCheckpoint(ctx context.Context, mode string) (walFrameN int, err error) {
// Ignore if there is no underlying database.View on GitHub (pinned to 4ed7a308f6)
Solutions
- Inspect the wrapped error to see whether it is a WAL read failure or a replica storage write failure.
- Validate replica storage credentials and permissions, then retry the sync.
- Free disk space if the failure involves staging LTX files locally.
- Run 'litestream reset' (or enable auto-recover) if LTX state is corrupt and cannot resync.
Defensive patterns
Strategy: retry
Validate before calling
if err := storageCheck(ctx); err != nil { /* verify replica backend auth + reachability before checkpointing */ } Try / catch
if err != nil && strings.Contains(err.Error(), "cannot snapshot after checkpoint") {
// inspect cause: WAL read vs storage write; retry; reset if corrupt
logAndRetry(err)
} Prevention
- Use expiring-credential rotation with refresh before expiry.
- Monitor disk space for LTX staging.
- Verify WAL integrity if external tools touch the database.
- Enable auto-recover for unattended resilience.
When it happens
Trigger: db.sync(ctx, true, exec, snapshotInfo, 0) fails during the post-checkpoint boundary snapshot: WAL frame read/checksum failure, LTX file creation failure on the replica backend, or storage client errors (network, auth, permissions).
Common situations: S3 credentials expired mid-run or bucket permissions revoked; WAL truncated by an external tool causing frame mismatch; disk full preventing LTX staging.
Related errors
- cannot copy wal before checkpoint: %w
- cannot copy wal after passive checkpoint: %w
- cannot copy wal after checkpoint: %w
- write ltx from db: %w
- cannot seal wal before passive checkpoint: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/bd915b140a8527b5.
Report an issue: GitHub.