gastownhall/beads · error
db: DependencySQLRepository.DetectCycles: %w
Error message
db: DependencySQLRepository.DetectCycles: %w
What it means
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.
Source
Thrown at internal/storage/domain/db/dependency.go:884
if _, ok := allowed[d.DependencyType]; ok {
out = append(out, d)
}
}
return out
}
func (r *dependencySQLRepositoryImpl) IsBlocked(ctx context.Context, issueID string, opts domain.DepListOpts) (bool, []string, error) {
blocked, blockers, err := issueops.IsBlockedInTx(ctx, r.runner, issueID)
if err != nil {
return false, nil, fmt.Errorf("db: DependencySQLRepository.IsBlocked %s: %w", issueID, err)
}
return blocked, blockers, nil
}
func (r *dependencySQLRepositoryImpl) DetectCycles(ctx context.Context) ([][]*types.Issue, error) {
out, err := issueops.DetectCyclesInTx(ctx, r.runner)
if err != nil {
return nil, fmt.Errorf("db: DependencySQLRepository.DetectCycles: %w", err)
}
return out, nil
}
func (r *dependencySQLRepositoryImpl) DetectCycleReport(ctx context.Context) (publicops.CycleReport, error) {
out, err := issueops.DetectCycleReportInTx(ctx, r.runner)
if err != nil {
return publicops.CycleReport{}, fmt.Errorf("db: DependencySQLRepository.DetectCycleReport: %w", err)
}
return out, nil
}
// WalkDependencyTree runs the SHARED walk body, unwrapped.
//
// It does NOT wrap the error the way its siblings above do, and that is the one
// thing to keep when editing it: the body publishes issueops.ErrValidation,
// storage.ErrNotFound and *issueops.ErrTooManyRows as the role's own vocabulary,
// and every one of those is classified by errors.Is/errors.As at both frontView on GitHub (pinned to 71377f2769)
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.
Example fix
// before cycles, err := repo.DetectCycles(ctx) // ctx has no deadline control // after ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() cycles, err := repo.DetectCycles(ctx)
Defensive patterns
Strategy: try-catch
Validate before calling
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
return fmt.Errorf("db unavailable before DetectCycles: %w", err)
} Type guard
func isContextDeadline(err error) bool {
return errors.Is(err, context.DeadlineExceeded)
} Try / catch
cycles, err := repo.DetectCycles(ctx)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
// retry with longer timeout or reduced scope
}
return fmt.Errorf("cycle detection: %w", err)
} Prevention
- 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).
When it happens
Trigger: Calling DetectCycles(ctx) when DetectCyclesInTx errors: failure reading the dependencies tables, connection loss, context cancellation, or driver error while building the graph.
Common situations: 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.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- db: DependencySQLRepository.CycleThroughEdges: %w
- db: DependencySQLRepository.DetectCycleReport: %w
- db: DependencySQLRepository.CycleThroughEdges (wisps): %w
- db: DependencySQLRepository.HasCycle: %w
- db: DependencySQLRepository.IsBlocked %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3215f51ccdea465c.
Report an issue: GitHub.