benbjohnson/litestream · error

calc pos: %w

Error message

calc pos: %w

What it means

During the first sync of a replica, syncOnce must determine the replica's current TXID position by listing remote LTX files (calcPos). If that discovery fails — unreadable/missing LTX header, listing error, or no usable files — the error is wrapped as 'calc pos'. Litestream cannot know where the replica stands and aborts the sync.

Source

Thrown at replica.go:187

	// Clear last position if if an error occurs during sync.
	defer func() {
		if err != nil {
			r.mu.Lock()
			r.pos = ltx.Pos{}
			r.mu.Unlock()
		}
	}()

	if err := ctx.Err(); err != nil {
		return result, context.Cause(ctx)
	}

	// Calculate current replica position, if unknown.
	if r.Pos().IsZero() {
		pos, err := r.calcPos(ctx)
		if err != nil {
			return result, fmt.Errorf("calc pos: %w", err)
		}
		r.SetPos(pos)
	}

	// Find current position of database.
	dpos, err := r.db.Pos()
	if err != nil {
		return result, fmt.Errorf("cannot determine current position: %w", err)
	} else if dpos.IsZero() {
		return result, errReplicaWaitForData
	}

	r.Logger().Debug("replica sync",
		slog.Group("txid",
			slog.String("replica", r.Pos().TXID.String()),
			slog.String("db", dpos.TXID.String()),
		))

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Inspect the wrapped error: if listing failed, fix credentials/region (see OSS GET/LIST errors); if a header is corrupt, the remote copy is damaged.
  2. Run 'litestream ltx -level all' / 'litestream replicas' against the replica to see what files exist remotely.
  3. For a genuinely empty/invalid remote state, run 'litestream reset <db>' to clear local LTX state and re-sync from scratch (or enable the auto-recover replica option to do this automatically).
  4. If the latest LTX file is truncated, restore from an earlier complete generation and re-establish replication.

Example fix

// before
replicas:
  - type: oss
    bucket: my-bucket
    path: db/ltx
// after (auto-recover clears bad local LTX state and re-syncs)
replicas:
  - type: oss
    bucket: my-bucket
    path: db/ltx
    auto-recover: true
Defensive patterns

Strategy: fallback

Try / catch

if err := replica.Sync(ctx); err != nil && strings.Contains(err.Error(), "calc pos") {
    // clear bad local LTX state and resync
    if rerr := resetAndResync(ctx); rerr != nil { return rerr }
}

Prevention

When it happens

Trigger: First sync after registering a replica when calcPos cannot read the latest LTX header: remote listing fails (403/404), the newest LTX file is corrupt/truncated, or the replica path contains no valid LTX files.

Common situations: Fresh replica pointing at an empty bucket path; remote files truncated by a failed earlier upload; credentials allowing listing but not reading; network blip during the initial position discovery. Also surfaces in TestReplica_SyncOnceLimitsLTXFiles when fixtures are malformed.

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/9af96379b195a76d. Report an issue: GitHub.