gastownhall/beads · error
reparent: add new parent %s: %w
Error message
reparent: add new parent %s: %w
What it means
Wraps a failure from depRepo.Insert while reparenting adds a new parent-child edge of type DepParentChild. The insert of one target parent failed after prior steps may have already run, so partial reparent state is possible. The underlying repository error is preserved via %w.
Source
Thrown at internal/storage/domain/dependency.go:432
}
if sameStringSet(existing, target) {
return nil
}
for _, oldParentID := range sortedSetDifference(existing, target) {
if _, err := u.depRepo.Delete(ctx, childID, oldParentID, actor, opts); err != nil {
return fmt.Errorf("reparent: remove old parent %s: %w", oldParentID, err)
}
}
for _, addParentID := range sortedSetDifference(target, existing) {
dep := &types.Dependency{
IssueID: childID,
DependsOnID: addParentID,
Type: types.DepParentChild,
}
if err := u.depRepo.Insert(ctx, dep, actor, opts); err != nil {
return fmt.Errorf("reparent: add new parent %s: %w", addParentID, err)
}
}
return nil
}
func sameStringSet(left, right map[string]struct{}) bool {
if len(left) != len(right) {
return false
}
for value := range left {
if _, ok := right[value]; !ok {
return false
}
}
return true
}
// sortedSetDifference returns the members of left absent from right, sorted soView on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped cause for duplicate/constraint violations
- Ensure the new parent ID exists before calling Reparent
- Retry the reparent — it diffs existing vs target and only adds missing edges
- Serialize reparent operations on the same child to avoid races
Example fix
// before
if err := u.depRepo.Insert(ctx, dep, actor, opts); err != nil {
return fmt.Errorf("reparent: add new parent %s: %w", addParentID, err)
}
// after
if err := u.depRepo.Insert(ctx, dep, actor, opts); err != nil && !dberrors.IsAlreadyExists(err) {
return fmt.Errorf("reparent: add new parent %s: %w", addParentID, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure target parent exists before reparent
parent, err := issueRepo.Get(ctx, addParentID)
if err != nil || parent == nil {
return fmt.Errorf("target parent %s does not exist", addParentID)
} Try / catch
if err := u.Reparent(ctx, childID, parents, actor, opts); err != nil {
if strings.Contains(err.Error(), "add new parent") {
// extract the failing parent ID from the message and check duplicates/existence
}
} Prevention
- Pre-validate all target parent IDs exist in the same table (issue vs wisp)
- Avoid concurrent reparents on the same child
- Retry the idempotent Reparent after transient failures
- Match Reparent vs ReparentWisp to the child's table
When it happens
Trigger: Calling Reparent or ReparentWisp where sortedSetDifference(target, existing) yields a parent ID and depRepo.Insert for that Dependency returns an error.
Common situations: Duplicate parent edge inserted concurrently by another actor; referential integrity failure because the target parent ID does not exist; DB write failure or context timeout.
Related errors
- reparent: remove old parent %s: %w
- GetForIssueIDs: %w
- GetForIssueIDs (wisps): %w
- list dep metadata: %w
- iter dep metadata: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8e12768be6fc35a0.
Report an issue: GitHub.