gastownhall/beads · error

ready claim of %s reported success but did not land (found a

Error message

ready claim of %s reported success but did not land (found assignee=%q status=%q, want %s) — server likely degraded; treat the claim as NOT applied

What it means

After a ready-claim write reported success, verifiedReadyClaim re-read the row and found assignee/status that do not satisfy the claim's postcondition (claimedBy(actor).want). This indicates the write was lost or reverted — likely a degraded server — so the library returns an error telling the caller to treat the claim as NOT applied.

Source

Thrown at internal/storage/dolt/issues.go:442

	claimed, err := write()
	if err != nil {
		return nil, err
	}
	if claimed == nil || !s.serverMode {
		return claimed, err
	}
	assignee, status, verr := s.readReadyClaimState(ctx, claimed.ID)
	if verr != nil {
		return nil, fmt.Errorf("ready claim of %s reported success but could not be verified (server degraded?): %w — re-read the issue before trusting the claim",
			claimed.ID, verr)
	}
	post := claimedBy(actor)
	if post.want(assignee, status) {
		return claimed, nil
	}
	doltMetrics.claimVerifyLost.Add(ctx, 1, metric.WithAttributes(
		attribute.String("op", "ready-claim")))
	return nil, fmt.Errorf("ready claim of %s reported success but did not land (found assignee=%q status=%q, want %s) — server likely degraded; treat the claim as NOT applied",
		claimed.ID, assignee, status, post.desc)
}

// HeartbeatIssue refreshes the lease on an issue actor holds in_progress,
// pushing lease_expires_at forward on its row in the ephemeral leases table
// (see issueops.lease). Deliberately NO DOLT_ADD/DOLT_COMMIT: the leases
// table is dolt_ignored, so a heartbeat mints no commit and no history — this
// is the whole point of bd-lrgn1 (fleet heartbeats were the dominant source
// of unbounded reachable history). Wrapped in withRetryTx so a heartbeat that
// loses Dolt's optimistic merge to a concurrent reclaim/close on the same
// lease row is replayed against a fresh snapshot rather than surfaced.
func (s *DoltStore) HeartbeatIssue(ctx context.Context, id, actor string) error {
	if s.isActiveWisp(ctx, id) {
		// Wisps are ephemeral and never leased; nothing to heartbeat.
		return fmt.Errorf("%w: %s is ephemeral", storage.ErrNotClaimable, id)
	}
	return s.withRetryTx(ctx, func(tx *sql.Tx) error {
		return issueops.HeartbeatIssueInTx(ctx, tx, id, actor)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat the claim as failed and re-run bd ready (or re-check bd ready) to see the current holder
  2. Check the actual assignee/status shown in the error; if another actor holds it, pick a different ready issue
  3. Investigate server health if claims are repeatedly lost (degraded/replayed writes)
  4. Upgrade/restart the Dolt server and verify write durability before resuming agent loops
Defensive patterns

Strategy: retry

Validate before calling

// Re-read the issue before assuming the claim landed
const { assignee, status } = await bd.show(issueId);
if (assignee !== expectedActor) throw new Error("claim not held by expected actor");

Type guard

function claimLandedFor(issue, actor) {
  return issue && issue.assignee === actor && issue.status === "in_progress";
}

Try / catch

try {
  await bd.readyClaim(actor);
} catch (e) {
  if (String(e.message).includes("did not land")) {
    // treat claim as NOT applied; refresh ready list and pick another issue
  } else throw e;
}

Prevention

When it happens

Trigger: Ready claim reports success, but readReadyClaimState returns an assignee/status that fails post.want(assignee, status) — e.g. another actor already holds the claim, the issue was closed concurrently, or the write silently did not persist.

Common situations: Two agents claiming the same ready issue concurrently; a Dolt server in a degraded state dropping writes; replica/leader divergence after failover.

Related errors


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