gastownhall/beads · error

inherit labels: childID must not be empty

Error message

inherit labels: childID 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 child issue ID is an empty string. Inheritance copies the parent's labels onto the child, so a child ID is mandatory. This is a pure argument-validation failure raised before any repository call.

Source

Thrown at internal/storage/domain/label.go:231

	}
	out, err := u.labelRepo.ListByIssueIDs(ctx, ids, LabelOpts{UseWispsTable: useWisp})
	if err != nil {
		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] {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure the child issue is created first and capture its returned ID before calling InheritFromParent.
  2. Check upstream code for a failed creation whose error was swallowed, leaving the ID empty.
  3. If the child may legitimately not exist yet, skip inheritance rather than calling with an empty ID.

Example fix

// before
child, _ := createChildIssue() // error ignored
uc.InheritFromParent(ctx, child.ID, parentID, actor, nil)
// after
child, err := createChildIssue()
if err != nil { return err }
if child.ID == "" { return fmt.Errorf("child issue has no ID") }
_, err = uc.InheritFromParent(ctx, child.ID, parentID, actor, nil)
Defensive patterns

Strategy: validation

Validate before calling

if childID == "" { return fmt.Errorf("child issue ID is required before inheriting labels") }

Type guard

func hasChildID(childID string) bool { return strings.TrimSpace(childID) != "" }

Prevention

When it happens

Trigger: Calling InheritFromParent(ctx, "", parentID, actor, skipExisting) or InheritFromWispParent(ctx, "", parentWispID, actor, skipExisting) — i.e., the child issue/wisp identifier was never assigned or was lost upstream.

Common situations: Code that creates a child issue but ignores the returned ID; deserializing a partially-filled issue struct where the ID field is empty; passing a variable that was never populated because an earlier creation step failed silently.

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


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