gastownhall/beads · error
%w: claim next requires an actor
Error message
%w: claim next requires an actor
What it means
ValidateClaimNextRequest rejects a claim-next request with an empty Actor field, wrapping storage.ErrValidation. Every claim requires a named actor so assignee, lease, and audit events can be attributed; anonymous claims are a contract violation shared by all backends.
Source
Thrown at internal/storage/issueops/claim_next.go:26
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/types"
publicops "github.com/steveyegge/beads/issueops"
)
// ClaimNextCommitMessage names the claim in the Dolt commit message, matching
// what the CLI's own per-command commit wrote before the claim moved onto the
// role. It is the only spelling: the id it names is the one the claim WON, so
// no caller could have composed it before the call.
func ClaimNextCommitMessage(issueID string) string {
return "bd: claim ready " + issueID
}
// ValidateClaimNextRequest applies the request rules every ReadyClaimer
// implementation shares. It lives here rather than in each of them because a
// rule enforced on one backend and not the other is not a contract.
func ValidateClaimNextRequest(request publicops.ClaimNextRequest) error {
if request.Actor == "" {
return fmt.Errorf("%w: claim next requires an actor", storage.ErrValidation)
}
if request.Filter.Limit != nil {
return fmt.Errorf("%w: claim next does not take a limit", storage.ErrValidation)
}
if request.Filter.Offset != 0 {
return fmt.Errorf("%w: claim next does not take an offset", storage.ErrValidation)
}
// Brief is refused for the reason Limit and Offset are, and the reason is
// sharper here: a claim does not read its row through the page's query at
// all. ExecuteClaimNext refetches the winning row whole (GetIssueInTx) and
// hydrates its counts itself, so the projection has nothing to apply to,
// and a claim that accepted the field would answer a MUTATING request with
// a fully-hydrated row carrying IsLitePartial=false — the caller's only
// signal that it did not get what it asked for, saying it did.
if request.Filter.Brief {
return fmt.Errorf("%w: claim next does not take a projection", storage.ErrValidation)
}
return nilView on GitHub (pinned to 71377f2769)
Solutions
- Pass --actor <name> on the command line
- Set the BEADS_ACTOR environment variable
- Ensure API callers populate ClaimNextRequest.Actor before validating
Example fix
// before
req := publicops.ClaimNextRequest{Filter: filter}
err := ValidateClaimNextRequest(req) // fails: requires an actor
// after
req := publicops.ClaimNextRequest{Filter: filter, Actor: os.Getenv("BEADS_ACTOR")}
if req.Actor == "" { req.Actor = username.Current() }
err := ValidateClaimNextRequest(req) Defensive patterns
Strategy: validation
Validate before calling
func ensureActor(req publicops.ClaimNextRequest) (publicops.ClaimNextRequest, error) {
if req.Actor == "" {
a := os.Getenv("BEADS_ACTOR")
if a == "" { u, err := user.Current(); if err != nil { return req, err }; a = u.Username }
req.Actor = a
}
if err := types.CheckFieldLen("actor", req.Actor); err != nil { return req, err }
return req, ValidateClaimNextRequest(req)
} Try / catch
if err := ValidateClaimNextRequest(req); err != nil {
if errors.Is(err, storage.ErrValidation) { return fmt.Errorf("fix request: %w", err) }
return err
} Prevention
- Always set --actor or BEADS_ACTOR, especially in CI/containers
- Populate ClaimNextRequest.Actor before calling validators
- Validate requests once at the boundary with ValidateClaimNextRequest
When it happens
Trigger: Calling ClaimReadyIssueInTx/ExecuteClaimNext (or any ReadyClaimer) with ClaimNextRequest{Actor: ""} — e.g. BEADS_ACTOR unset and no --actor flag passed.
Common situations: Running `bd claim` in a CI/container where BEADS_ACTOR isn't set and whoami falls back to empty; scripts invoking the Go API without populating the request struct; ValidateCloseBatchRequest re-validating the same rules and hitting the shared validator.
Related errors
- identity: invalid proxy secret
- backend must be set
- repo %q must use OWNER/REPO or HOST/OWNER/REPO
- repo %q contains an empty path component
- repo %q contains invalid character %q
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d83db5f5c4916c1b.
Report an issue: GitHub.