gastownhall/beads · error

reparent: list current parent: %w

Error message

reparent: list current parent: %w

What it means

Wraps a failure of depRepo.ListByIssueIDs when reparent reads the child's current parent-child edges before computing the set replacement. Reparenting replaces the child's whole existing parent set (a child can carry multiple parent-child edges), so this read is the first durable step; when it fails, no edges have been changed yet and the error pinpoints the read as the failure point.

Source

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

	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
	// swap of one edge. Diffing the whole existing set against the target set
	// is the same rule the store-backed backends apply in
	// issueops.ApplyParentPatch; that body cannot be called from here because
	// internal/storage/issueops imports this package (bd-yby99.26).
	existing := map[string]struct{}{}
	for _, dep := range res.Outgoing[childID] {
		if dep.Type == types.DepParentChild {
			existing[dep.DependsOnID] = struct{}{}
		}
	}
	target := map[string]struct{}{}
	if newParentID != "" {
		target[newParentID] = struct{}{}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix the wrapped repository error surfaced by %w (connectivity, SQL, context).
  2. Retry the reparent — the read is side-effect-free, so re-invoking is safe.
  3. Increase the context deadline if large edge sets are timing out.
  4. Check database health and schema currency (bd doctor) before retrying batch reparents.

Example fix

// before: assuming reparent failed during the write
if err := uc.Reparent(ctx, child, parent, actor); err != nil {
    rollbackParentWrite(child) // wrong: nothing was written
}
// after: the failure was the pre-write read; just retry
if err := uc.Reparent(ctx, child, parent, actor); err != nil {
    if isTransient(err) {
        err = uc.Reparent(ctx, child, parent, actor)
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Confirm storage is reachable before starting reparent batch
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("storage unreachable: %w", err)
}
// Optionally pre-fetch the child's current parents to fail fast
_, err := uc.ListByWispIDs(ctx, []string{childID}, DepListFilter{})

Try / catch

err := uc.Reparent(ctx, childID, newParentID, actor)
for attempt := 0; err != nil && attempt < 3; attempt++ {
    if !errors.Is(err, context.DeadlineExceeded) && !isTransient(err) {
        break
    }
    time.Sleep(backoff(attempt))
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    err = uc.Reparent(ctx, childID, newParentID, actor)
}

Prevention

When it happens

Trigger: Reparent or ReparentWisp calls ListByIssueIDs for the child filtered to DepParentChild / outgoing direction, and the repo query fails — DB connection lost, SQL error, Dolt lock/transaction conflict, or context cancellation during the scan.

Common situations: Database unavailable mid-command; context deadline exceeded for children with many edges; Dolt server error during concurrent sync; schema/version mismatch after an upgrade.

Related errors


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