{"record":{"id":"7cef9534074ff68d","repo":"gastownhall/beads","slug":"add-deps-d-hierarchy-check-w","errorCode":null,"errorMessage":"add deps[%d]: hierarchy check: %w","messagePattern":"add deps\\[(.+?)\\]: hierarchy check: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/dependency.go","lineNumber":730,"sourceCode":"\twispSources, err := u.depRepo.WispSourceIDs(ctx, sources)\n\tif err != nil {\n\t\treturn BulkAddDepsResult{}, fmt.Errorf(\"add deps: classify sources: %w\", err)\n\t}\n\t// Parent-child edges must be visible before blocking edges in the same\n\t// request. The shared repository guard can then evaluate existing + planned\n\t// ancestry without widening #4034 into #4035's combined-graph cycle check.\n\tfor phase := 0; phase < 2; phase++ {\n\t\tparentPhase := phase == 0\n\t\tfor i, dep := range deps {\n\t\t\tif (dep.Type == types.DepParentChild) != parentPhase {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := u.depRepo.ValidateBlockingHierarchy(ctx, dep); err != nil {\n\t\t\t\tvar hierarchyConflict *DependencyHierarchyConflictError\n\t\t\t\tif errors.As(err, &hierarchyConflict) {\n\t\t\t\t\treturn BulkAddDepsResult{}, err\n\t\t\t\t}\n\t\t\t\treturn BulkAddDepsResult{}, fmt.Errorf(\"add deps[%d]: hierarchy check: %w\", i, err)\n\t\t\t}\n\t\t\tif !opts.SkipPerEdgeCycleCheck && types.IsSchedulingEdge(dep.Type) {\n\t\t\t\tcycle, err := u.depRepo.HasCycle(ctx, dep.IssueID, dep.DependsOnID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn BulkAddDepsResult{}, fmt.Errorf(\"add deps[%d]: cycle check: %w\", i, err)\n\t\t\t\t}\n\t\t\t\tif cycle {\n\t\t\t\t\treturn BulkAddDepsResult{}, cycleErrorf(\"add deps[%d]: adding %s -> %s would create a cycle\", i, dep.IssueID, dep.DependsOnID)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The explicit `bd dep add` / `bd link` verb on the proxied server\n\t\t\t// (cmd/bd/dep_proxied_server.go, link_proxied_server.go) records a\n\t\t\t// dependency_added event for each genuine new edge — unlike\n\t\t\t// create-with-deps, which calls depRepo.Insert directly without\n\t\t\t// EmitEvent. UseWispsTable routes both the edge and that event to\n\t\t\t// the source's own pair of tables.\n\t\t\t_, sourceIsWisp := wispSources[dep.IssueID]\n\t\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/dependency.go#L712-L748","documentation":"Before inserting each blocking edge, AddDependencies calls ValidateBlockingHierarchy on the repository. This error wraps any failure of that check other than a *DependencyHierarchyConflictError (which is returned unwrapped so callers can errors.As it). It means the hierarchy validation itself failed to run (storage error) or returned a non-typed error.","triggerScenarios":"Calling AddDependencies with a scheduling/blocking edge where depRepo.ValidateBlockingHierarchy returns an error that is not a DependencyHierarchyConflictError — e.g. a query failure while walking parent-child ancestry.","commonSituations":"Storage backend errors during ancestry traversal; partially corrupted dependency tables; context cancellation mid-hierarchy-walk on a large graph.","solutions":["Read the wrapped error after the 'hierarchy check:' prefix to find the real cause","If you expected a hierarchy conflict (e.g. blocking a child against its parent), match *DependencyHierarchyConflictError via errors.As — that path returns the typed error directly","Retry after confirming database health (bd doctor)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check parent-child relationships so blocking edges you know conflict\n// with ancestry are not submitted at all","typeGuard":"var hc *domain.DependencyHierarchyConflictError\nif errors.As(err, &hc) { /* typed hierarchy conflict: handle specifically */ }","tryCatchPattern":"if err != nil {\n    var hc *domain.DependencyHierarchyConflictError\n    if errors.As(err, &hc) { return err } // typed path\n    // otherwise wrapped as 'hierarchy check:' — storage issue, inspect cause\n}","preventionTips":["Match *DependencyHierarchyConflictError with errors.As for policy conflicts","Verify ancestry (parent/child) of endpoints before adding blocking edges","Keep database healthy to avoid traversal failures on large graphs"],"tags":["dependencies","hierarchy","validation"],"backgroundTag":"hierarchy-validation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}