gastownhall/beads · error
inherit labels: parentID must not be empty
Error message
inherit labels: parentID must not be empty
What it means
A guard error thrown by the label inheritance use-case (inherit in internal/storage/domain/label.go) when the parent issue ID is an empty string. The parent's labels are the source for inheritance, so a parent ID is required. Raised before any repository access.
Source
Thrown at internal/storage/domain/label.go:234
return nil, fmt.Errorf("get labels bulk: %w", err)
}
return out, nil
}
func (u *labelUseCaseImpl) InheritFromParent(ctx context.Context, childID, parentID, actor string, skipExisting []string) ([]string, error) {
return u.inherit(ctx, childID, parentID, actor, skipExisting, false)
}
func (u *labelUseCaseImpl) InheritFromWispParent(ctx context.Context, childWispID, parentWispID, actor string, skipExisting []string) ([]string, error) {
return u.inherit(ctx, childWispID, parentWispID, actor, skipExisting, true)
}
func (u *labelUseCaseImpl) inherit(ctx context.Context, childID, parentID, actor string, skipExisting []string, useWisp bool) ([]string, error) {
if childID == "" {
return nil, fmt.Errorf("inherit labels: childID must not be empty")
}
if parentID == "" {
return nil, fmt.Errorf("inherit labels: parentID must not be empty")
}
parentLabels, err := u.labelRepo.List(ctx, parentID, LabelOpts{UseWispsTable: useWisp})
if err != nil {
return nil, fmt.Errorf("inherit labels: list parent %s: %w", parentID, err)
}
if len(parentLabels) == 0 {
return nil, nil
}
skip := make(map[string]bool, len(skipExisting))
for _, s := range skipExisting {
skip[s] = true
}
var inherited []string
for _, label := range parentLabels {
if skip[label] {
continue
}
if err := u.labelRepo.Insert(ctx, childID, label, actor, LabelOpts{UseWispsTable: useWisp}); err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Resolve and verify the parent issue ID before calling inheritance (e.g., from the issue's dependency or parent field).
- If the issue genuinely has no parent, skip inheritance for it instead of calling with an empty ID.
- Validate parentID non-empty at the call site and return a clearer domain error there.
Example fix
// before
var parentID string // never assigned
uc.InheritFromParent(ctx, childID, parentID, actor, nil)
// after
if parentID == "" { return nil } // no parent: nothing to inherit
uc.InheritFromParent(ctx, childID, parentID, actor, nil) Defensive patterns
Strategy: validation
Validate before calling
if parentID == "" { return nil } // no parent: skip inheritance Type guard
func hasParentID(parentID string) bool { return strings.TrimSpace(parentID) != "" } Prevention
- Resolve the parent relationship explicitly; skip inheritance when there is none.
- Never pass zero-value struct fields as IDs.
- Validate parent references after deserializing configs/JSON.
When it happens
Trigger: Calling InheritFromParent(ctx, childID, "", actor, skipExisting) or InheritFromWispParent(ctx, childWispID, "", actor, skipExisting) — the parent reference was never resolved or an empty parent struct field was passed.
Common situations: A dependency lookup returned no parent (e.g., issue has no 'blocks/blocked-by' or parent relationship) and the code passed the zero-value ID; JSON configs missing the parent field; wisps whose parent pointer was never set.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- inherit labels: childID must not be empty
- add label: id must not be empty
- add label: label must not be empty
- remove label: id must not be empty
- remove label: label must not be empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/fb4baa3c482a90a7.
Report an issue: GitHub.