gastownhall/beads · error

ReclaimExpiredLeases: %w

Error message

ReclaimExpiredLeases: %w

What it means

ReclaimExpiredLeases wraps any error returned by the underlying issue repository's lease-reclaim operation. The use-case layer adds the 'ReclaimExpiredLeases:' prefix so callers can tell which storage operation failed while preserving the original driver/DB error via %w. It indicates lease reclaim (taking over expired leases on issues/wisps) could not be completed.

Source

Thrown at internal/storage/domain/issue.go:1937

// WakeExpiredDefers returns every expired DATED defer to open (see
// issueops.WakeExpiredDefersInTx) and reports how many permanent issues and
// wisps woke. The caller owns persistence: commit with a wake message iff
// issues > 0, and with the ephemeral plain-COMMIT form iff only wisps woke
// (wisp tables are dolt_ignored, so their wake needs a SQL commit but must
// mint no version commit).
func (u *issueUseCaseImpl) WakeExpiredDefers(ctx context.Context) (issues, wisps int, err error) {
	issues, wisps, err = u.issueRepo.WakeExpiredDefers(ctx)
	if err != nil {
		return 0, 0, fmt.Errorf("WakeExpiredDefers: %w", err)
	}
	return issues, wisps, nil
}

func (u *issueUseCaseImpl) ReclaimExpiredLeases(ctx context.Context, olderThan time.Duration, filter types.ReclaimFilter, actor string) ([]types.ReclaimedLease, error) {
	out, err := u.issueRepo.ReclaimExpiredLeases(ctx, olderThan, filter, actor)
	if err != nil {
		return nil, fmt.Errorf("ReclaimExpiredLeases: %w", err)
	}
	return out, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error chain (errors.Unwrap / %v of the error) to find the underlying driver failure
  2. Verify the Dolt database is reachable and the server is up (bd dolt status / connection settings)
  3. Retry the reclaim after the storage layer recovers; the operation is safe to re-run
  4. If SQL/schema errors appear, run the beads migration/upgrade path to reconcile the schema

Example fix

// before
issues, err := uc.ReclaimExpiredLeases(ctx, ttl, filter, actor)
if err != nil {
	return err // loses context
}
// after
if err != nil {
	log.Printf("lease reclaim failed: %v", err) // log full wrapped chain
	var recov bool
	if errors.As(err, &driverErr) { recov = retryReclaim(ctx) }
	return fmt.Errorf("reclaim: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// check storage reachability before reclaim
if err := pingDolt(ctx); err != nil {
	return fmt.Errorf("storage unavailable, skipping reclaim: %w", err)
}

Try / catch

out, err := uc.ReclaimExpiredLeases(ctx, ttl, filter, actor)
if err != nil {
	var wrapped error
	if errors.As(err, &wrapped) { log.Printf("reclaim failed, driver says: %v", wrapped) }
	return fmt.Errorf("reclaim: %w", err) // safe to retry later
}

Prevention

When it happens

Trigger: Calling issueUseCaseImpl.ReclaimExpiredLeases(ctx, olderThan, filter, actor) when the underlying issueRepo.ReclaimExpiredLeases query fails — e.g. Dolt/DB connection error, SQL error in the reclaim UPDATE/SELECT, or storage layer unavailable.

Common situations: Background lease-reclaim sweeps running while the Dolt database is restarting or unreachable; schema drift between beads versions causing SQL errors; concurrent write contention during a batch reclaim.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/9041bd0f097b596f. Report an issue: GitHub.