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

  1. Inspect the wrapped error to see whether it is a WAL read failure or a replica storage write failure.
  2. Validate replica storage credentials and permissions, then retry the sync.
  3. Free disk space if the failure involves staging LTX files locally.
  4. 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

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


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/bd915b140a8527b5. Report an issue: GitHub.