gastownhall/beads · warning · storage.ErrValidation
%w: add dependencies requires an actor
Error message
%w: add dependencies requires an actor
What it means
ValidateAddDependenciesRequest enforces that every dependency-creation request names the actor performing the change, because beads records who added each dependency for audit and permission purposes. When request.Actor is empty the request is rejected, wrapped with storage.ErrValidation so callers can errors.Is() it. This is a pure validation error raised before any database work.
Source
Thrown at internal/storage/issueops/dependency_editor.go:30
)
// ValidateAddDependenciesRequest applies the request rules every
// DependencyEditor 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.
//
// The self-dependency refusal is here, ahead of the per-edge cycle probe and
// for EVERY edge type, for the reason the domain path states: a blocking
// self-edge otherwise trips the cycle check and reports the wrong refusal, and
// SkipPerEdgeCycleCheck would skip it entirely.
//
// The type check is that there IS a type — non-empty, within the column's
// length. It is deliberately not a membership test: the vocabulary is an open,
// workspace-configurable set (see the Dep* constants), so refusing an unlisted
// type would refuse a workspace's own.
func ValidateAddDependenciesRequest(request publicops.AddDependenciesRequest) error {
if request.Actor == "" {
return fmt.Errorf("%w: add dependencies requires an actor", storage.ErrValidation)
}
if len(request.Edges) == 0 {
return fmt.Errorf("%w: add dependencies requires at least one edge", storage.ErrValidation)
}
for i, edge := range request.Edges {
if edge.IssueID == "" || edge.DependsOnID == "" {
return fmt.Errorf("%w: add dependencies edge %d requires both endpoints", storage.ErrValidation, i)
}
if !edge.Type.IsValid() {
return fmt.Errorf("%w: add dependencies edge %d requires a dependency type (max %d chars)",
storage.ErrValidation, i, types.MaxDependencyTypeLen)
}
if edge.IssueID == edge.DependsOnID {
return fmt.Errorf("%w: %s cannot depend on itself", domain.ErrSelfDependency, edge.IssueID)
}
}
return nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Set request.Actor to the active identity (configured user, agent name, or authenticated principal).
- Configure the identity source (e.g. bd config / env) so callers always have an actor available.
- Reject empty actors at your own boundary before invoking the storage layer.
- Check errors.Is(err, storage.ErrValidation) to confirm it's this validation, not a storage failure.
Example fix
// before
req := publicops.AddDependenciesRequest{Edges: edges}
// after
req := publicops.AddDependenciesRequest{Actor: "agent:claude", Edges: edges} Defensive patterns
Strategy: validation
Validate before calling
if req.Actor == "" {
return fmt.Errorf("actor must be set (e.g. \"agent:claude\") before calling AddDependencies")
} Type guard
func hasActor(req publicops.AddDependenciesRequest) bool { return req.Actor != "" } Try / catch
err := store.AddDependencies(ctx, req)
if errors.Is(err, storage.ErrValidation) {
// re-prompt for identity or fix request construction
} Prevention
- Resolve the actor from a single identity helper so it's never empty.
- Construct requests through a constructor that requires an actor parameter.
- Always set Actor in automated/agent scripts.
When it happens
Trigger: Calling AddDependencies (or building a publicops.AddDependenciesRequest) with Actor left as the zero value "" — e.g. CLI/agent code that didn't capture the current user identity.
Common situations: Automated scripts constructing requests manually without setting Actor; refactors that removed the actor plumbing; sessions with no configured user identity.
Related errors
- no store is open for this workspace
- no absolute native user directory is available
- ExternalDoltConfig: set either Socket OR (Host, Port), not b
- ExternalDoltConfig: must set Socket or (Host, Port)
- ExternalDoltConfig: Host requires Port
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ba7c53ae097ce108.
Report an issue: GitHub.