gastownhall/beads · error

reparent: childID must not be empty

Error message

reparent: childID must not be empty

What it means

Guard error from reparent (backing Reparent and ReparentWisp): childID is the empty string. Reparenting requires knowing which child to move; the use case refuses before any repository work. A newParentID of "" is not caught here explicitly (only the childID==newParentID equality check follows), so the empty child is the guarded precondition.

Source

Thrown at internal/storage/domain/dependency.go:382

		return fmt.Errorf("remove dep: sourceID and dependsOnID must not be empty")
	}
	if _, err := u.depRepo.Delete(ctx, sourceID, dependsOnID, actor, DepInsertOpts{UseWispsTable: useWisp, EmitEvent: true}); err != nil {
		return fmt.Errorf("remove dep %s -> %s: %w", sourceID, dependsOnID, err)
	}
	return nil
}

func (u *dependencyUseCaseImpl) Reparent(ctx context.Context, childID, newParentID, actor string) error {
	return u.reparent(ctx, childID, newParentID, actor, false)
}

func (u *dependencyUseCaseImpl) ReparentWisp(ctx context.Context, childWispID, newParentID, actor string) error {
	return u.reparent(ctx, childWispID, newParentID, actor, true)
}

func (u *dependencyUseCaseImpl) reparent(ctx context.Context, childID, newParentID, actor string, useWisp bool) error {
	if childID == "" {
		return fmt.Errorf("reparent: childID must not be empty")
	}
	if childID == newParentID {
		return fmt.Errorf("reparent: %s cannot be its own parent", childID)
	}

	opts := DepInsertOpts{UseWispsTable: useWisp}
	res, err := u.depRepo.ListByIssueIDs(ctx, []string{childID}, DepListOpts{
		Types:         []types.DependencyType{types.DepParentChild},
		Direction:     DepDirectionOut,
		UseWispsTable: useWisp,
	})
	if err != nil {
		return fmt.Errorf("reparent: list current parent: %w", err)
	}

	// A child can carry MORE THAN ONE parent-child edge — Create accepts
	// CreateRequest.ParentID and an explicit parent-child entry in
	// Dependencies in the same request — so this is a set replacement, not a

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check childID for emptiness before calling Reparent / ReparentWisp.
  2. Resolve the child issue via lookup first and abort with a clear message if it cannot be found.
  3. Fix the upstream parse/config that produced the blank ID.
  4. In batch reparent jobs, skip or log entries with empty IDs instead of passing them through.

Example fix

// before
err := uc.Reparent(ctx, childID, newParentID, actor)
// after
if childID == "" {
    return fmt.Errorf("reparent skipped: child id missing")
}
err := uc.Reparent(ctx, childID, newParentID, actor)
Defensive patterns

Strategy: validation

Validate before calling

func readyToReparent(childID, newParentID string) error {
    if childID == "" {
        return fmt.Errorf("childID must not be empty")
    }
    if childID == newParentID {
        return fmt.Errorf("child cannot be its own parent")
    }
    return nil
}
if err := readyToReparent(childID, newParentID); err != nil {
    return err
}
err := uc.Reparent(ctx, childID, newParentID, actor)

Type guard

func validChildID(id string) bool { return id != "" }

Try / catch

if !validChildID(childID) {
    return fmt.Errorf("reparent skipped: missing child id")
}
if err := uc.Reparent(ctx, childID, newParentID, actor); err != nil {
    return fmt.Errorf("reparent failed: %w", err)
}

Prevention

When it happens

Trigger: Reparent(ctx, "", parentID, actor) or ReparentWisp with an empty child ID — usually a failed upstream lookup, a blank CLI argument, or a struct field left at its zero value before the call.

Common situations: Scripts re-parenting issues from a list where one ID failed to resolve; YAML/JSON config with a missing child key; passing a *types.Issue whose ID was never persisted.

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/afd017b3a47d7c53. Report an issue: GitHub.