gastownhall/beads · error
inherit labels: insert %s on %s: %w
Error message
inherit labels: insert %s on %s: %w
What it means
Wraps a failure from labelRepo.Insert while copying one parent label onto the child during inheritance (internal/storage/domain/label.go). The message names the specific label and child ID that failed. Note the return passes back any labels already inherited, so partial progress is visible to the caller.
Source
Thrown at internal/storage/domain/label.go:253
}
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 {
return inherited, fmt.Errorf("inherit labels: insert %s on %s: %w", label, childID, err)
}
inherited = append(inherited, label)
}
return inherited, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause to see if it's a duplicate/unique-constraint error; if so, add the label to skipExisting or tolerate duplicates.
- Check for concurrent processes performing inheritance on the same child; serialize the operation.
- Verify database writability (not read-only, not locked) and retry.
- Use the partially returned inherited list to resume without re-inserting succeeded labels.
Example fix
// before
inherited, err := uc.InheritFromParent(ctx, childID, parentID, actor, nil)
if err != nil { return err } // loses partial progress
// after
inherited, err := uc.InheritFromParent(ctx, childID, parentID, actor, nil)
if err != nil {
// inherited may be non-empty; retry with it as skipExisting
_, err = uc.InheritFromParent(ctx, childID, parentID, actor, inherited)
if err != nil { return err }
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check existing child labels to build skipExisting existing, _ := uc.GetLabels(ctx, childID) skip := existing // pass as skipExisting
Try / catch
inherited, err := uc.InheritFromParent(ctx, childID, parentID, actor, skip)
if err != nil {
// resume with labels already applied to avoid duplicate inserts
_, err = uc.InheritFromParent(ctx, childID, parentID, actor, inherited)
if err != nil { return err }
} Prevention
- Pass existing child labels as skipExisting to avoid duplicate inserts.
- Serialize inheritance for the same child across processes.
- Treat the partially returned inherited list as progress for resumable retries.
When it happens
Trigger: Calling InheritFromParent or InheritFromWispParent where an Insert of a parent label onto childID fails: duplicate label already on child (unique constraint), database lock, context canceled mid-loop, or wisps-table insert into a missing table.
Common situations: Concurrent inheritance runs both inserting the same label; a unique index on (issue_id, label) rejecting a race the skipExisting list didn't cover; DB file locked by another bd process during long batch operations.
Related errors
- failed to get wisp labels: %w
- get labels bulk: %w
- inherit labels: list parent %s: %w
- get issues by IDs: labels from %s: %w
- ErrTransaction
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/1032101968a2ff6a.
Report an issue: GitHub.