gastownhall/beads · warning · domain.ErrSelfDependency
%w: %s cannot depend on itself
Error message
%w: %s cannot depend on itself
What it means
Self-dependencies (an issue depending on itself) are rejected because they're meaningless and would pollute the dependency graph. The validator compares IssueID and DependsOnID per edge and fails with domain.ErrSelfDependency (wrapped) plus the offending issue ID. This is distinct from storage.ErrValidation so callers can distinguish graph-rule violations from generic request validation.
Source
Thrown at internal/storage/issueops/dependency_editor.go:44
// 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
}
// ValidateRemoveDependencyRequest applies the request rules every
// DependencyEditor implementation shares for a removal.
func ValidateRemoveDependencyRequest(request publicops.RemoveDependencyRequest) error {
if request.Actor == "" {
return fmt.Errorf("%w: remove dependency requires an actor", storage.ErrValidation)
}
if request.IssueID == "" || request.DependsOnID == "" {
return fmt.Errorf("%w: remove dependency requires both endpoints", storage.ErrValidation)
}
return nil
}
// AddDependenciesCommitMessage is the history entry an edge assertion records.View on GitHub (pinned to 71377f2769)
Solutions
- Filter edges where IssueID == DependsOnID before building the request.
- Match errors.Is(err, domain.ErrSelfDependency) to detect this case programmatically.
- Fix the upstream edge-generation logic so source issues are excluded from their own dependency lists.
- Verify ID normalization (case/whitespace) isn't accidentally making two IDs equal.
Example fix
// before
edges := buildEdges(issueID, mentionedIDs) // may include issueID itself
// after
edges := buildEdges(issueID, mentionedIDs)
edges = slices.DeleteFunc(edges, func(e publicops.DependencyEdge) bool {
return e.IssueID == e.DependsOnID
}) Defensive patterns
Strategy: validation
Validate before calling
req.Edges = slices.DeleteFunc(req.Edges, func(e publicops.DependencyEdge) bool {
return e.IssueID == e.DependsOnID
}) Type guard
func isSelfDependency(e publicops.DependencyEdge) bool {
return e.IssueID == e.DependsOnID
} Try / catch
err := store.AddDependencies(ctx, req)
if errors.Is(err, domain.ErrSelfDependency) {
// skip the self-edge; not a data-integrity problem
} Prevention
- Filter self-edges in any edge-generation/import code.
- Normalize IDs (trim/case) before comparing endpoints.
- Never pass the same issue ID to both sides of a dependency flag in CLI usage.
When it happens
Trigger: Calling AddDependencies with an edge where IssueID == DependsOnID — e.g. generated edges from data where both endpoints resolved to the same issue, or CLI arguments where the user passed the same ID twice.
Common situations: Bulk imports where a normalized/uppercased ID matched itself; scripts computing edges from text mentions that included the source issue; user typos entering the same bd-xxx twice.
Related errors
- ExternalDoltConfig: TLSKey set without TLSCert
- 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)
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0d46ec0df801ccdd.
Report an issue: GitHub.