gastownhall/beads · error

dependency graph: rows %s: %w

Error message

dependency graph: rows %s: %w

What it means

After iterating a dependency table's rows, appendDependencyGraphInTx checks rows.Err() and wraps any deferred iteration error as 'dependency graph: rows <table>: %w'. This catches driver-level failures that surface mid-iteration (connection drop, query abort) rather than at query or scan time.

Source

Thrown at internal/storage/issueops/cycles.go:117

			FROM %s
		`, DepTargetExpr, depTable))
		if err != nil {
			return fmt.Errorf("dependency graph: query %s: %w", depTable, err)
		}
		for rows.Next() {
			var issueID, dependsOnID, depType string
			if err := rows.Scan(&issueID, &dependsOnID, &depType); err != nil {
				_ = rows.Close()
				return fmt.Errorf("dependency graph: scan %s: %w", depTable, err)
			}
			t := types.DependencyType(depType)
			if t == types.DepBlocks || t == types.DepConditionalBlocks || (includeParentChild && t == types.DepParentChild) {
				graph[issueID] = append(graph[issueID], dependsOnID)
			}
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("dependency graph: rows %s: %w", depTable, err)
		}
	}
	return nil
}

// CycleThroughEdgesInGraph reports a rendered cycle that traverses
// one of the new edges (issueID -> dependsOnID pairs), or "" when no new edge
// lies on a cycle. An edge u -> v is on a cycle exactly when u is reachable
// from v, so this is precise where cycle enumeration is not: a DFS-based
// detector records one cycle per back edge and can report a pre-existing
// cycle through the same nodes instead of the one the new edge created
// (bd-578h9.9). The graph must already contain the new edges.
func CycleThroughEdgesInGraph(graph map[string][]string, edges [][2]string) string {
	for _, edge := range edges {
		source, target := edge[0], edge[1]
		if source == "" || target == "" {
			continue
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error for transport/timeout causes and retry the operation
  2. Reduce graph size or batch the check to shorten row streaming
  3. Ensure a stable DB connection (timeouts, keepalives) for remote backends

Example fix

// before
// treat nil error after loop as success only
// after
if err := rows.Err(); err != nil { return fmt.Errorf("...: %w", err) } // already present; retry op on failure
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.HasPrefix(err.Error(), "dependency graph: rows ") {
    cause := errors.Unwrap(err)
    // transient network/backend error: backoff and retry the whole operation
    return err
}

Prevention

When it happens

Trigger: The rows iterator encounters a transport/backend error while streaming rows of a dependency table during graph assembly — network drop to the DB, server abort, timeout.

Common situations: Large graphs over flaky/remote Dolt connections; query timeouts on very wide dependency tables; server restart mid-scan.

Related errors


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