benbjohnson/litestream · error

cannot determine L%d max ltx file for %q: %w

Error message

cannot determine L%d max ltx file for %q: %w

What it means

Wraps a failure from Replica.MaxLTXFileInfo when determining the maximum LTX file at a given level for the database, used to populate the maxLTXFileInfos cache. It is thrown when neither cached nor locally-known info exists and the remote max-file lookup fails.

Source

Thrown at db.go:3288

		return 0, exec.pos, err
	}
	return h.Sum64(), exec.pos, nil
}

// MaxLTXFileInfo returns the metadata for the last LTX file in a level.
// If cached, it will returned the local copy. Otherwise, it fetches from the replica.
func (db *DB) MaxLTXFileInfo(ctx context.Context, level int) (ltx.FileInfo, error) {
	db.maxLTXFileInfos.Lock()
	defer db.maxLTXFileInfos.Unlock()

	info, ok := db.maxLTXFileInfos.m[level]
	if ok {
		return *info, nil
	}

	remoteInfo, err := db.Replica.MaxLTXFileInfo(ctx, level)
	if err != nil {
		return ltx.FileInfo{}, fmt.Errorf("cannot determine L%d max ltx file for %q: %w", level, db.Path(), err)
	}

	db.maxLTXFileInfos.m[level] = &remoteInfo
	return remoteInfo, nil
}

// DefaultRestoreParallelism is the default parallelism when downloading WAL files.
const DefaultRestoreParallelism = 8

// DefaultFollowInterval is the default polling interval for follow mode.
const DefaultFollowInterval = 1 * time.Second

// IntegrityCheckMode specifies the level of integrity checking after restore.
type IntegrityCheckMode int

const (
	IntegrityCheckNone IntegrityCheckMode = iota
	IntegrityCheckQuick

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check the wrapped inner error to separate auth, network, and not-found causes.
  2. Verify the replica URL (bucket, path, region/endpoint) in the litestream config.
  3. Confirm credentials have ListBucket/Get permissions on the prefix.
  4. Retry after transient failures; the lookup is read-only and cached on success.
  5. If the bucket is intentionally empty, ensure the caller tolerates a zero TXID rather than erroring.

Example fix

// before
remoteInfo, err := db.Replica.MaxLTXFileInfo(ctx, level)
if err != nil { return ltx.FileInfo{}, fmt.Errorf("cannot determine L%d max ltx file for %q: %w", level, db.Path(), err) }
// after (pre-flight init)
if err := db.Replica.Client.Init(ctx); err != nil { return ltx.FileInfo{}, fmt.Errorf("init replica: %w", err) }
remoteInfo, err := db.Replica.MaxLTXFileInfo(ctx, level)
if err != nil { return ltx.FileInfo{}, fmt.Errorf("cannot determine L%d max ltx file for %q: %w", level, db.Path(), err) }
Defensive patterns

Strategy: retry

Validate before calling

if err := db.Replica.Client.Init(ctx); err != nil { return fmt.Errorf("replica init failed: %w", err) }

Try / catch

info, err := db.Replica.MaxLTXFileInfo(ctx, level)
if err != nil {
    if isTransient(err) { return retryWithBackoff(ctx) }
    return fmt.Errorf("cannot determine L%d max ltx file: %w", level, err)
}

Prevention

When it happens

Trigger: Operations needing the latest remote LTX file at a level (restore position checks, compaction decisions) when MaxLTXFileInfo's listing fails: storage outage, auth failure, or an unreachable/misnamed bucket (db.go:3288).

Common situations: First sync against a freshly configured replica with wrong credentials; network partition during compaction; typo'd bucket or path in the config.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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