benbjohnson/litestream · error

page size mismatch: got

Error message

page size mismatch: got %d, expected %d

What it means

FetchPage returned a page whose byte length differs from the VFS file's configured page size (f.pageSizeBytes / len(buf)). Litestream assumes every LTX page image matches the database page size; a mismatch means the replica data and the local page size disagree, so copying it would corrupt the page buffer.

Solutions

  1. Verify the remote database snapshot's page size matches the local VFS database page size; do not share replicas across differently-configured databases.
  2. Inspect the LTX file at the indexed offset (litestream ltx -level 0) for truncation/corruption.
  3. Re-replicate: run litestream reset for the database so a fresh snapshot with the correct page size is created.
  4. Check for interrupted uploads/partial writes at the storage backend and re-upload affected LTX files.
  5. Ensure the client app doesn't change PRAGMA page_size on an existing replicated database.
Defensive patterns

Strategy: validation

Validate before calling

// Verify snapshot page size matches local DB before pointing VFS at a replica:
// read bytes 16-17 of the DB header (page size) and compare with remote snapshot config.
localPS := binary.BigEndian.Uint16(header[16:18]) // must equal replica page size

Type guard

func pageSizeOK(data []byte, want uint32) bool { return uint32(len(data)) == want }

Try / catch

if err := readPageForWrite(pgno, buf); err != nil {
    if strings.Contains(err.Error(), "page size mismatch") {
        // stop writes; re-replicate with matching page size
    }
}

Prevention

When it happens

Trigger: Calling WriteAt (read-modify-write path) on a page present in f.index but whose stored LTX record was written with a different page size — e.g. the remote snapshot was created from a database with a different page_size, or a truncated/corrupt LTX record yields a short read.

Common situations: Pointing a VFS at a replica from a different database with a different PRAGMA page_size; restoring across litestream versions where page-size handling changed; corrupted or truncated LTX files on storage (partial upload); manually copied replica data between databases.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


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

Appendix: source

Thrown at vfs.go:1717

	if data, ok := f.cache.Get(pgno); ok {
		copy(buf, data)
		return nil
	}

	// Get page index element
	elem, ok := f.index[pgno]
	if !ok {
		return fmt.Errorf("page not found: %d", pgno)
	}

	// Fetch from remote
	_, data, err := FetchPage(f.ctx, f.client, elem.Level, elem.MinTXID, elem.MaxTXID, elem.Offset, elem.Size)
	if err != nil {
		return err
	}

	if uint32(len(data)) != pageSize {
		return fmt.Errorf("page size mismatch: got %d, expected %d", len(data), pageSize)
	}

	copy(buf, data)
	f.cache.Add(pgno, data)
	return nil
}

func (f *VFSFile) Truncate(size int64) error {
	f.logger.Debug("truncating file", "size", size)

	pageSize, err := f.pageSizeBytes()
	if err != nil {
		return err
	}

	newCommit := uint32(size / int64(pageSize))

	f.mu.Lock()

View on GitHub (pinned to 4ed7a308f6)