gastownhall/beads · error

db: DependencySQLRepository.CycleThroughEdges: %w

Error message

db: DependencySQLRepository.CycleThroughEdges: %w

What it means

CycleThroughEdges builds a scheduling graph from the dependencies table via AppendSchedulingGraphInTx, then checks whether the given edges would close a cycle. This wrapper means loading the core dependencies table into the graph failed. Only non-empty edge lists reach the query; empty input returns "", nil without touching the database.

Source

Thrown at internal/storage/domain/db/dependency.go:944

	maxDepth := opts.MaxDepth
	if maxDepth <= 0 {
		maxDepth = 50
	}
	reverse := opts.Direction == domain.DepDirectionIn
	out, err := issueops.GetDependencyTreeInTx(ctx, r.runner, rootID, maxDepth, opts.ShowAllPaths, reverse)
	if err != nil {
		return nil, fmt.Errorf("db: DependencySQLRepository.GetTree: %w", err)
	}
	return out, nil
}

func (r *dependencySQLRepositoryImpl) CycleThroughEdges(ctx context.Context, edges [][2]string) (string, error) {
	if len(edges) == 0 {
		return "", nil
	}
	graph := make(map[string][]string)
	if err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{"dependencies"}, graph); err != nil {
		return "", fmt.Errorf("db: DependencySQLRepository.CycleThroughEdges: %w", err)
	}
	if err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{"wisp_dependencies"}, graph); err != nil && !dberrors.IsTableNotExist(err) {
		return "", fmt.Errorf("db: DependencySQLRepository.CycleThroughEdges (wisps): %w", err)
	}
	return issueops.CycleThroughEdgesInGraph(graph, edges), nil
}

// WispSourceIDs classifies a batch of ids by plane in one scoped query. It is
// the proxied twin of the in-tx probe the store-backed dependency editor runs,
// and shares its implementation so the two answer the same question — down to
// treating a missing wisps table as "no wisps" rather than an error.
func (r *dependencySQLRepositoryImpl) WispSourceIDs(ctx context.Context, ids []string) (map[string]struct{}, error) {
	set, err := issueops.WispIDSetInTx(ctx, r.runner, ids)
	if err != nil {
		return nil, fmt.Errorf("db: DependencySQLRepository.WispSourceIDs: %w", err)
	}
	return set, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Unwrap to see the root SQL/driver error from AppendSchedulingGraphInTx.
  2. Verify the dependencies table exists and the schema is migrated.
  3. Check database connectivity and retry.
  4. Increase context timeout for large dependency graphs.

Example fix

// before
edge, err := repo.CycleThroughEdges(ctx, edges) // bare ctx, server down
// after: ensure server reachable first
if err := db.PingContext(ctx); err != nil { return err }
edge, err := repo.CycleThroughEdges(ctx, edges)
Defensive patterns

Strategy: validation

Validate before calling

if len(edges) == 0 {
    return nil // library returns "", nil without DB access for empty input
}
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("db unreachable before cycle check: %w", err)
}

Type guard

func hasEdges(edges [][2]string) bool { return len(edges) > 0 }

Try / catch

edge, err := repo.CycleThroughEdges(ctx, edges)
if err != nil {
    if dberrors.IsTableNotExist(errors.Unwrap(err)) {
        // missing dependencies table: treat as no graph
        return "", nil
    }
    return fmt.Errorf("cycle check: %w", err)
}

Prevention

When it happens

Trigger: Calling CycleThroughEdges(ctx, edges) with at least one edge pair, where AppendSchedulingGraphInTx for the "dependencies" table fails: table missing/corrupt, connection error, or context cancellation.

Common situations: Pre-flight cycle checks before adding an edge, run against a stopped Dolt server; missing dependencies table after a bad migration; deadline exceeded 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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/2120d00d9780dc07. Report an issue: GitHub.