{"record":{"id":"3215f51ccdea465c","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-detectcycles-w","errorCode":null,"errorMessage":"db: DependencySQLRepository.DetectCycles: %w","messagePattern":"db: DependencySQLRepository\\.DetectCycles: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":884,"sourceCode":"\t\tif _, ok := allowed[d.DependencyType]; ok {\n\t\t\tout = append(out, d)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc (r *dependencySQLRepositoryImpl) IsBlocked(ctx context.Context, issueID string, opts domain.DepListOpts) (bool, []string, error) {\n\tblocked, blockers, err := issueops.IsBlockedInTx(ctx, r.runner, issueID)\n\tif err != nil {\n\t\treturn false, nil, fmt.Errorf(\"db: DependencySQLRepository.IsBlocked %s: %w\", issueID, err)\n\t}\n\treturn blocked, blockers, nil\n}\n\nfunc (r *dependencySQLRepositoryImpl) DetectCycles(ctx context.Context) ([][]*types.Issue, error) {\n\tout, err := issueops.DetectCyclesInTx(ctx, r.runner)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: DependencySQLRepository.DetectCycles: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (r *dependencySQLRepositoryImpl) DetectCycleReport(ctx context.Context) (publicops.CycleReport, error) {\n\tout, err := issueops.DetectCycleReportInTx(ctx, r.runner)\n\tif err != nil {\n\t\treturn publicops.CycleReport{}, fmt.Errorf(\"db: DependencySQLRepository.DetectCycleReport: %w\", err)\n\t}\n\treturn out, nil\n}\n\n// WalkDependencyTree runs the SHARED walk body, unwrapped.\n//\n// It does NOT wrap the error the way its siblings above do, and that is the one\n// thing to keep when editing it: the body publishes issueops.ErrValidation,\n// storage.ErrNotFound and *issueops.ErrTooManyRows as the role's own vocabulary,\n// and every one of those is classified by errors.Is/errors.As at both front","sourceCodeStart":866,"sourceCodeEnd":902,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L866-L902","documentation":"DetectCycles calls issueops.DetectCyclesInTx, which loads the dependency graph and finds dependency cycles. This wrapper means the underlying cycle-detection query/graph load failed; the repository adds only context. It is not a report that cycles were found — that is returned as data, not as an error.","triggerScenarios":"Calling DetectCycles(ctx) when DetectCyclesInTx errors: failure reading the dependencies tables, connection loss, context cancellation, or driver error while building the graph.","commonSituations":"Running bd doctor or integrity checks against an unavailable database; schema mismatch (older database missing tables DetectCyclesInTx expects); long-running detection hitting a context deadline on large graphs.","solutions":["Unwrap to find the root driver/SQL error.","Ensure the database is running and schema is current (run migrations/doctor).","Increase the context deadline for large dependency graphs.","Retry after transient connectivity failures."],"exampleFix":"// before\ncycles, err := repo.DetectCycles(ctx) // ctx has no deadline control\n// after\nctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)\ndefer cancel()\ncycles, err := repo.DetectCycles(ctx)","handlingStrategy":"try-catch","validationCode":"ctx, cancel := context.WithTimeout(ctx, 60*time.Second)\ndefer cancel()\nif err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db unavailable before DetectCycles: %w\", err)\n}","typeGuard":"func isContextDeadline(err error) bool {\n    return errors.Is(err, context.DeadlineExceeded)\n}","tryCatchPattern":"cycles, err := repo.DetectCycles(ctx)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        // retry with longer timeout or reduced scope\n    }\n    return fmt.Errorf(\"cycle detection: %w\", err)\n}","preventionTips":["Give cycle detection a generous context timeout on large graphs.","Run migrations so expected tables always exist.","Distinguish 'cycles found' (returned data) from detection errors (wrapped error)."],"tags":["database","cycle-detection","graph","wrapper"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}