{"record":{"id":"83516a10456735f3","repo":"gastownhall/beads","slug":"reparent-remove-old-parent-s-w","errorCode":null,"errorMessage":"reparent: remove old parent %s: %w","messagePattern":"reparent: remove old parent (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/dependency.go","lineNumber":421,"sourceCode":"\t// issueops.ApplyParentPatch; that body cannot be called from here because\n\t// internal/storage/issueops imports this package (bd-yby99.26).\n\texisting := map[string]struct{}{}\n\tfor _, dep := range res.Outgoing[childID] {\n\t\tif dep.Type == types.DepParentChild {\n\t\t\texisting[dep.DependsOnID] = struct{}{}\n\t\t}\n\t}\n\ttarget := map[string]struct{}{}\n\tif newParentID != \"\" {\n\t\ttarget[newParentID] = struct{}{}\n\t}\n\tif sameStringSet(existing, target) {\n\t\treturn nil\n\t}\n\n\tfor _, oldParentID := range sortedSetDifference(existing, target) {\n\t\tif _, err := u.depRepo.Delete(ctx, childID, oldParentID, actor, opts); err != nil {\n\t\t\treturn fmt.Errorf(\"reparent: remove old parent %s: %w\", oldParentID, err)\n\t\t}\n\t}\n\n\tfor _, addParentID := range sortedSetDifference(target, existing) {\n\t\tdep := &types.Dependency{\n\t\t\tIssueID:     childID,\n\t\t\tDependsOnID: addParentID,\n\t\t\tType:        types.DepParentChild,\n\t\t}\n\t\tif err := u.depRepo.Insert(ctx, dep, actor, opts); err != nil {\n\t\t\treturn fmt.Errorf(\"reparent: add new parent %s: %w\", addParentID, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc sameStringSet(left, right map[string]struct{}) bool {\n\tif len(left) != len(right) {","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/dependency.go#L403-L439","documentation":"Wraps a failure from depRepo.Delete while reparenting removes an old parent-child dependency edge. The child's existing parent set is being diffed against the target set and one of the removals failed at the repository layer. The wrap preserves the underlying cause (e.g. DB error, context cancellation).","triggerScenarios":"Calling Reparent or ReparentWisp where sortedSetDifference(existing, target) yields an old parent ID and depRepo.Delete returns an error for (childID, oldParentID).","commonSituations":"Database connectivity loss mid-reparent; context cancelled or timed out during the batch; storage-level constraint or concurrent modification of the same dependency rows.","solutions":["Inspect the wrapped %w cause to identify the repository-level failure","Retry the reparent once the DB/context issue is resolved (it is idempotent: already-removed edges are skipped)","Verify the child and parent IDs exist in the expected table (issues vs wisps)","Check context deadline/cancellation propagation"],"exampleFix":"// before\nif _, err := u.depRepo.Delete(ctx, childID, oldParentID, actor, opts); err != nil {\n\treturn fmt.Errorf(\"reparent: remove old parent %s: %w\", oldParentID, err)\n}\n// after (survive transient removal issues, verify at end)\nif _, err := u.depRepo.Delete(ctx, childID, oldParentID, actor, opts); err != nil && !dberrors.IsNotExist(err) {\n\treturn fmt.Errorf(\"reparent: remove old parent %s: %w\", oldParentID, err)\n}","handlingStrategy":"retry","validationCode":"// verify both IDs are non-empty and the edge exists\nif childID == \"\" || oldParentID == \"\" {\n\treturn fmt.Errorf(\"child and old parent IDs required\")\n}\ndeps, _ := u.GetForIssueIDs(ctx, []string{childID})","typeGuard":null,"tryCatchPattern":"if err := u.Reparent(ctx, childID, newParents, actor, opts); err != nil {\n\tvar wrapped interface{ Unwrap() error }\n\tif errors.As(err, &target) { /* inspect root cause */ }\n\t// reparent is idempotent; safe to retry\n}","preventionTips":["Reuse Reparent's idempotence: retry the whole call instead of manual edge surgery","Keep reparent calls serialized per child ID","Pass a context with a generous deadline","Log oldParentID from the message to target repairs"],"tags":["storage","dependency","reparent","wrapped-error"],"backgroundTag":"dependency-delete-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}