benbjohnson/litestream · error

cannot build index: %w

Error message

cannot build index: %w

What it means

Raised during VFSFile.Open when buildIndex fails to construct the page index from the replica's LTX file infos. The index maps page numbers to their location in LTX files; without it the VFS cannot serve any page reads. The underlying error is also logged at Error level with context.

Source

Thrown at vfs.go:1160

	}
	f.pos = pos

	// Initialize write support TXID tracking
	if f.writeEnabled {
		f.expectedTXID = pos.TXID
		f.pendingTXID = pos.TXID + 1
		f.logger.Debug("write support enabled", "expectedTXID", f.expectedTXID, "pendingTXID", f.pendingTXID)

		// Initialize write buffer file for durability (discards any existing buffer)
		if err := f.initWriteBuffer(); err != nil {
			return fmt.Errorf("initialize write buffer: %w", err)
		}
	}

	// Build the page index so we can lookup individual pages.
	if err := f.buildIndex(f.ctx, infos); err != nil {
		f.logger.Error("cannot build index", "error", err)
		return fmt.Errorf("cannot build index: %w", err)
	}

	// Start background hydration if enabled
	if f.hydrationPath != "" {
		if err := f.initHydration(infos); err != nil {
			f.logger.Warn("hydration initialization failed, continuing without hydration", "error", err)
			f.hydrationPath = ""
		}
	}

	// Continuously monitor the replica client for new LTX files.
	f.wg.Add(1)
	go func() { defer f.wg.Done(); f.monitorReplicaClient(f.ctx) }()

	// Start periodic sync goroutine if write support is enabled
	if f.writeEnabled && f.syncInterval > 0 {
		f.syncTicker = time.NewTicker(f.syncInterval)
		f.syncStop = make(chan struct{})

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Validate replica LTX files (litestream ltx -level all) and re-replicate if corrupt
  2. Check replica storage connectivity/credentials and retry
  3. Run litestream reset for the database if local LTX state is inconsistent
  4. Increase client timeouts / retry so large index builds aren't cancelled

Example fix

// before
f, err := file.Open(ctx) // transient S3 timeout -> "cannot build index"
// after
var ferr *vfs.FileError
f, err := file.Open(ctx)
if errors.As(err, &ferr) || isTransient(err) {
    time.Sleep(time.Second); f, err = file.Open(ctx) // retry
}
Defensive patterns

Strategy: retry

Validate before calling

infos, err := client.LTXInfos(ctx)
for _, info := range infos { if err := verifyLTX(ctx, client, info); err != nil { return err } }

Try / catch

if err := file.Open(ctx); err != nil {
    if strings.Contains(err.Error(), "cannot build index") && isTransient(err) {
        ctx2, cancel := context.WithTimeout(context.Background(), 60*time.Second)
        defer cancel(); return file.Open(ctx2)
    }
    return err
}

Prevention

When it happens

Trigger: buildIndex fails while reading LTX page indexes from the replica client: corrupt/truncated LTX file, network error to the storage backend, page-size mismatch between infos, or context cancellation during a slow listing/read.

Common situations: Corrupt LTX files in the bucket (interrupted upload); S3/replica connectivity or IAM issues mid-open; opening a replica that mixes generations with different page sizes; short client timeouts on large replicas.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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