benbjohnson/litestream · error

create page cache: %w

Error message

create page cache: %w

What it means

Raised during VFSFile.Open when constructing the LRU page cache fails. lru.New essentially only fails when the entry capacity is invalid (<= 0), meaning CacheSize was misconfigured relative to the detected page size. Open aborts since reads depend on the cache.

Source

Thrown at vfs.go:1134

		}
		return err
	}

	pageSize, err := detectPageSizeFromInfos(f.ctx, f.client, infos)
	if err != nil {
		f.logger.Error("cannot detect page size", "error", err)
		return fmt.Errorf("detect page size: %w", err)
	}
	f.pageSize = pageSize

	// Initialize page cache. Convert byte size to number of pages.
	cacheEntries := f.CacheSize / int(pageSize)
	if cacheEntries < 1 {
		cacheEntries = 1
	}
	cache, err := lru.New[uint32, []byte](cacheEntries)
	if err != nil {
		return fmt.Errorf("create page cache: %w", err)
	}
	f.cache = cache

	// Determine the current position based off the latest LTX file.
	var pos ltx.Pos
	if len(infos) > 0 {
		pos = ltx.Pos{TXID: infos[len(infos)-1].MaxTXID}
	}
	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 {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Set CacheSize in the VFS config to a sane positive value (e.g. >= a few MB)
  2. Verify the detected page size is sane by checking the replica's LTX header
  3. Ensure pageSize is not 0 before dividing (guard in config loading)
  4. Update litestream if the LTX header layout seems incompatible

Example fix

// before
f.CacheSize = 0 // misconfig
cacheEntries := f.CacheSize / int(pageSize) // 0 -> lru.New error
// after
f.CacheSize = 16 * 1024 * 1024 // at least several pages
if f.CacheSize < int(pageSize) { f.CacheSize = int(pageSize) }
Defensive patterns

Strategy: validation

Validate before calling

if cfg.CacheSize <= 0 { return errors.New("CacheSize must be a positive byte value") }

Type guard

func cacheSizeValid(n int) bool { return n > 0 && n < math.MaxInt32 }

Try / catch

if err := file.Open(ctx); err != nil {
    if strings.Contains(err.Error(), "create page cache") {
        return fmt.Errorf("bad CacheSize config: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: lru.New[uint32, []byte](cacheEntries) returns an error — practically only when cacheEntries computed from f.CacheSize / pageSize is zero or negative and the guard was bypassed, e.g. integer overflow with a huge CacheSize or pageSize of 0 from a bad detection.

Common situations: CacheSize config set to 0 or a negative/huge value; a corrupt LTX header reporting a bogus page size making the division overflow.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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