{"record":{"id":"3edc71ad3ea1d545","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-gettree-w","errorCode":null,"errorMessage":"db: DependencySQLRepository.GetTree: %w","messagePattern":"db: DependencySQLRepository\\.GetTree: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":933,"sourceCode":"func (r *dependencySQLRepositoryImpl) CountEdges(ctx context.Context, req publicops.EdgeCountRequest) (publicops.EdgeCountResult, error) {\n\treturn issueops.ExecuteEdgeCount(ctx, r.runner, req)\n}\n\nfunc (r *dependencySQLRepositoryImpl) GetTree(ctx context.Context, rootID string, opts domain.DepTreeOpts) ([]*types.TreeNode, error) {\n\tif rootID == \"\" {\n\t\treturn nil, errors.New(\"db: DependencySQLRepository.GetTree: rootID must not be empty\")\n\t}\n\tif opts.Direction == domain.DepDirectionBoth {\n\t\treturn nil, errors.New(\"db: DependencySQLRepository.GetTree: DepDirectionBoth not supported; callers must invoke once per direction and merge\")\n\t}\n\tmaxDepth := opts.MaxDepth\n\tif maxDepth <= 0 {\n\t\tmaxDepth = 50\n\t}\n\treverse := opts.Direction == domain.DepDirectionIn\n\tout, err := issueops.GetDependencyTreeInTx(ctx, r.runner, rootID, maxDepth, opts.ShowAllPaths, reverse)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: DependencySQLRepository.GetTree: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (r *dependencySQLRepositoryImpl) CycleThroughEdges(ctx context.Context, edges [][2]string) (string, error) {\n\tif len(edges) == 0 {\n\t\treturn \"\", nil\n\t}\n\tgraph := make(map[string][]string)\n\tif err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{\"dependencies\"}, graph); err != nil {\n\t\treturn \"\", fmt.Errorf(\"db: DependencySQLRepository.CycleThroughEdges: %w\", err)\n\t}\n\tif err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{\"wisp_dependencies\"}, graph); err != nil && !dberrors.IsTableNotExist(err) {\n\t\treturn \"\", fmt.Errorf(\"db: DependencySQLRepository.CycleThroughEdges (wisps): %w\", err)\n\t}\n\treturn issueops.CycleThroughEdgesInGraph(graph, edges), nil\n}\n","sourceCodeStart":915,"sourceCodeEnd":951,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L915-L951","documentation":"GetTree calls issueops.GetDependencyTreeInTx with the root ID, a maxDepth (defaulting to 50), ShowAllPaths, and direction-derived reverse flag. This wrapper means the underlying tree-walk query failed. Note that within a transaction this walk runs unwrapped internally; this error surfaces only when the in-tx implementation itself returns an error.","triggerScenarios":"Calling GetTree(ctx, rootID, maxDepth, opts) when GetDependencyTreeInTx errors: SQL failure traversing dependencies, connection loss, context cancellation, or excessive recursion/depth query errors.","commonSituations":"Traversing from a root in a corrupted or partially migrated database; context timeout while walking a deep tree; database restarted mid-walk.","solutions":["Unwrap to find the root SQL/driver error.","Reduce maxDepth or set ShowAllPaths=false if the walk times out on large trees.","Verify schema and connectivity; retry transient failures.","Confirm the root ID belongs to an existing issue."],"exampleFix":"// before\ntree, err := repo.GetTree(ctx, rootID, 0, opts) // deep tree, default 50 depth\n// after: cap depth for large graphs\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()\ntree, err := repo.GetTree(ctx, rootID, 10, opts)","handlingStrategy":"validation","validationCode":"if rootID == \"\" {\n    return errors.New(\"GetTree requires a non-empty root issue ID\")\n}\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()","typeGuard":"func validTreeRequest(rootID string, maxDepth int) bool {\n    return rootID != \"\" && (maxDepth > 0 || maxDepth == 0) // 0 => default 50\n}","tryCatchPattern":"tree, err := repo.GetTree(ctx, rootID, maxDepth, opts)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return repo.GetTree(ctx, rootID, 10, opts) // shallower retry\n    }\n    return fmt.Errorf(\"dep tree %s: %w\", rootID, err)\n}","preventionTips":["Validate the root ID exists before walking.","Cap maxDepth for very large dependency graphs.","Disable ShowAllPaths when a single path suffices to cut query cost."],"tags":["database","tree-traversal","dependencies","wrapper"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}