benbjohnson/litestream · error

page map: %w

Error message

page map: %w

What it means

WALReader.pageMap failed while building the map of changed page numbers and latest frame contents, bounded by maxSyncWALBytes. This scan is the core of staging a sync; a read or parse error mid-scan aborts the whole sync for this iteration.

Source

Thrown at db.go:2082

			}
		} else if err != nil {
			return result, fmt.Errorf("new wal reader with offset: %w", err)
		}
	}

	// Build a mapping of changed page numbers and their latest content.
	db.setSyncDiagPhase(diagPhaseSyncPageMap,
		func(s *diagState) {
			s.txID = txID
			s.snapshotting = info.snapshotting
			s.reason = info.reason
		})
	if info.snapshotting {
		maxSyncWALBytes = 0
	}
	pageMap, maxOffset, walCommit, limited, err := rd.pageMap(ctx, maxSyncWALBytes)
	if err != nil {
		return result, fmt.Errorf("page map: %w", err)
	}
	result.limited = limited
	if walCommit > 0 {
		commit = walCommit
	}
	var sz int64
	if maxOffset > 0 {
		sz = maxOffset - info.offset
	}
	assert(sz >= 0, fmt.Sprintf("wal size must be positive: sz=%d, maxOffset=%d, info.offset=%d", sz, maxOffset, info.offset))
	db.setSyncDiagPhase(diagPhaseSyncPrepareLTX,
		func(s *diagState) {
			s.txID = txID
			s.walSize = sz
			s.snapshotting = info.snapshotting
			s.reason = info.reason
		})

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Retry — transient races with live checkpointing typically succeed on the next sync
  2. Force a checkpoint via the application (PRAGMA wal_checkpoint(TRUNCATE)) and restart Litestream for a clean snapshot
  3. Check for WAL corruption; restore from backup if frames are physically damaged
  4. Verify disk health and sufficient I/O headroom for large WALs
Defensive patterns

Strategy: retry

Validate before calling

// ensure WAL is at least header-sized and stable before sync
st, err := os.Stat(dbPath + "-wal")
ready := err == nil && st.Size() >= 32

Try / catch

if err := db.SyncAndWait(ctx); err != nil && strings.Contains(err.Error(), "page map") {
	if !errors.Is(err, context.Canceled) {
		backoffRetry(err)
	}
}

Prevention

When it happens

Trigger: rd.pageMap(ctx, maxSyncWALBytes) errors: I/O read failure mid-WAL, a frame whose checksum/validation fails, context cancellation, or a commit frame inconsistent with earlier frames.

Common situations: WAL being rewritten concurrently by SQLite during the scan; corrupted WAL frames after a crash; disk errors; huge WALs hitting I/O timeouts under memory pressure.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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