gastownhall/beads · error
db: DependencySQLRepository.HasCycle: %w
Error message
db: DependencySQLRepository.HasCycle: %w
What it means
Wraps a failure from WouldCreateSchedulingCycleInTx inside HasCycle, which detects whether adding issueID -> dependsOnID would create a scheduling cycle. This is a query/execution failure of the cycle-detection traversal, not a 'cycle found' result (a found cycle returns (true, nil)).
Source
Thrown at internal/storage/domain/db/dependency.go:404
// Snapshot only after all derived blocked-state maintenance has completed.
// Never gated on opts.EmitEvent — a structural removal is as real to a
// replaying consumer as one from an explicit dep verb.
if err := issueops.RecordDepEventInTx(ctx, r.runner, issueops.EventDepRemove, issueID, depType, dependsOnID, depMetadata, actor); err != nil {
return domain.DepDeleteResult{}, err
}
return domain.DepDeleteResult{Found: true, Type: dt, DependsOnID: dependsOnID}, nil
}
func (r *dependencySQLRepositoryImpl) HasCycle(ctx context.Context, issueID, dependsOnID string) (bool, error) {
if issueID == "" || dependsOnID == "" {
return false, errors.New("db: DependencySQLRepository.HasCycle: issueID and dependsOnID must not be empty")
}
cycle, err := issueops.WouldCreateSchedulingCycleInTx(ctx, r.runner, issueID, dependsOnID, nil)
if err != nil {
return false, fmt.Errorf("db: DependencySQLRepository.HasCycle: %w", err)
}
return cycle, nil
}
func (r *dependencySQLRepositoryImpl) ListByIssueIDs(ctx context.Context, issueIDs []string, opts domain.DepListOpts) (domain.DepBulkResult, error) {
result := domain.DepBulkResult{
Outgoing: make(map[string][]*types.Dependency),
Incoming: make(map[string][]*types.Dependency),
}
if len(issueIDs) == 0 {
return result, nil
}
idPlaceholders, idArgs := buildInPlaceholders(issueIDs)
typeWhere, typeArgs := buildTypeFilter(opts.Types)
table := pickDepTable(opts.UseWispsTable)
if opts.Direction == domain.DepDirectionBoth || opts.Direction == domain.DepDirectionOut {View on GitHub (pinned to 71377f2769)
Solutions
- Increase the context timeout and retry HasCycle; the check is read-only and safe to repeat.
- Break very large dependency graphs into smaller scopes or pre-check only the direct neighborhood.
- Check DB connectivity/server health if failures are systemic.
- Ensure IDs reference existing issues; non-existent rows can break some traversal implementations.
Example fix
// before cycle, err := deps.HasCycle(ctx, a, b) // ctx with 1s deadline // after ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() cycle, err := deps.HasCycle(ctx, a, b)
Defensive patterns
Strategy: retry
Validate before calling
if issueID == "" || dependsOnID == "" { return errors.New("both IDs required") }
if err := ctx.Err(); err != nil { return err } Try / catch
cycle, err := deps.HasCycle(ctx, a, b)
if err != nil {
if isTransientDBError(err) { // retry read-only check
cycle, err = deps.HasCycle(ctxWithLongerDeadline, a, b)
}
if err != nil { return err } // do NOT treat err as cycle-found
} Prevention
- Never interpret a non-nil error from HasCycle as 'cycle exists' — only (true, nil) means a cycle.
- Give deep-graph cycle checks a generous context timeout.
- Validate IDs are non-empty and reference existing issues before calling.
- Keep the dep table schema current with migrations.
When it happens
Trigger: Calling HasCycle(ctx, issueID, dependsOnID) with valid non-empty IDs, then the recursive cycle-detection query fails: connection error, timeout on deep graphs, context cancellation, or schema/driver error.
Common situations: Deep or wide dependency graphs making the traversal slow enough to hit context deadlines; Dolt server under load; passing an empty ID would instead hit a different validation error, so this one means the query itself broke.
Related errors
- db: DependencySQLRepository.Delete: record dependency_remove
- db: DependencySQLRepository.Delete: affected set: %w
- db: DependencySQLRepository.Delete: recompute is_blocked: %w
- db: DependencySQLRepository.DetectCycles: %w
- db: DependencySQLRepository.DetectCycleReport: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/cb77d71f694d550c.
Report an issue: GitHub.