benbjohnson/litestream · error

no ltx file available to determine page size

Error message

no ltx file available to determine page size

What it means

Litestream's VFS page-size detection reads the header of the newest LTX file in the replica to learn the database's page size. When the replica contains no LTX files at all (the file listing comes back empty), it cannot determine a page size and returns this error. It indicates the remote has no backup data to read from, not a malformed file.

Source

Thrown at vfs.go:2801

}

func detectPageSizeFromInfos(ctx context.Context, client ReplicaClient, infos []*ltx.FileInfo) (uint32, error) {
	var lastErr error
	for i := len(infos) - 1; i >= 0; i-- {
		pageSize, err := readPageSizeFromInfo(ctx, client, infos[i])
		if err != nil {
			lastErr = err
			continue
		}
		if !isSupportedPageSize(pageSize) {
			return 0, fmt.Errorf("unsupported page size: %d", pageSize)
		}
		return pageSize, nil
	}
	if lastErr != nil {
		return 0, fmt.Errorf("read ltx header: %w", lastErr)
	}
	return 0, fmt.Errorf("no ltx file available to determine page size")
}

func readPageSizeFromInfo(ctx context.Context, client ReplicaClient, info *ltx.FileInfo) (uint32, error) {
	rc, err := client.OpenLTXFile(ctx, info.Level, info.MinTXID, info.MaxTXID, 0, ltx.HeaderSize)
	if err != nil {
		return 0, fmt.Errorf("open ltx file: %w", err)
	}
	defer rc.Close()
	dec := ltx.NewDecoder(rc)
	if err := dec.DecodeHeader(); err != nil {
		return 0, fmt.Errorf("decode ltx header: %w", err)
	}
	return dec.Header().PageSize, nil
}

func isSupportedPageSize(pageSize uint32) bool {
	switch pageSize {
	case 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536:

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Verify the replica actually has LTX objects (litestream ltx -level all or list the bucket prefix)
  2. Run a litestream replicate sync to populate the remote before opening via VFS
  3. Check the config: correct bucket, path/prefix and database path — a wrong prefix lists zero files
  4. If local LTX state is corrupted, use litestream reset and re-replicate

Example fix

// before: opening VFS against an empty replica prefix
client, _ := litestreamvfs.Open(ctx, "s3://my-bucket/wrong-prefix/db")
// after: point at the prefix the replicator writes to and confirm files exist
client, _ := litestreamvfs.Open(ctx, "s3://my-bucket/litestream/db")
Defensive patterns

Strategy: validation

Validate before calling

infos, err := client.ListLTXFiles(ctx)
if err != nil { return err }
if len(infos) == 0 { return fmt.Errorf("replica has no ltx files; run replicate first") }

Try / catch

if err := openVFS(ctx); err != nil {
    if strings.Contains(err.Error(), "no ltx file available") {
        return syncReplicaFirst(ctx)
    }
    return err
}

Prevention

When it happens

Trigger: Calling restore/VFS open against a replica whose CalcRestorePlan yields zero files — e.g. a freshly configured replica that has never had a successful sync, or after all LTX files were pruned/deleted from storage.

Common situations: Pointing a VFS client at a brand-new bucket/prefix before the first litestream sync ran; wrong replica path so the listing finds nothing; retention/lifecycle rules deleted all objects; using `litestream reset` on a replica with no prior snapshots.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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