gastownhall/beads · error

get dependency records: rows: %w

Error message

get dependency records: rows: %w

What it means

After iterating rows in getDependencyRecordsIntoFromTable, rows.Err() reported a streaming failure, wrapped as 'get dependency records: rows: %w'. The result set broke partway through (connection drop, server abort), so the accumulated per-issue dependency map may be incomplete and the whole call fails. This is the per-ID-list analogue of the full-table rows iteration error.

Source

Thrown at internal/storage/issueops/dependency_queries.go:132

		}
		rows, err := tx.QueryContext(ctx, fmt.Sprintf(
			`SELECT issue_id, %s AS depends_on_id, type, created_at, created_by, metadata, thread_id
			 FROM %s WHERE issue_id IN (%s) ORDER BY issue_id, depends_on_id, type, id`,
			DepTargetExpr, depTable, strings.Join(placeholders, ",")), args...)
		if err != nil {
			return fmt.Errorf("get dependency records from %s: %w", depTable, err)
		}
		for rows.Next() {
			dep, scanErr := scanDependencyRow(rows)
			if scanErr != nil {
				_ = rows.Close()
				return fmt.Errorf("get dependency records: scan: %w", scanErr)
			}
			result[dep.IssueID] = append(result[dep.IssueID], dep)
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("get dependency records: rows: %w", err)
		}
	}
	return nil
}

// GetDependentRecordsForIssuesInTx returns raw dependency rows keyed by TARGET
// id: for each id in targetIDs, the rows whose target is that id — its INCOMING
// edges, i.e. its dependents — spanning BOTH the durable and wisp dependency
// tables and applying NO type filter or visibility policy (the caller filters
// at hydration). It is the batched, target-keyed mirror of the source-keyed
// GetDependencyRecordsForIssuesInTx: one query per table per batch of
// queryBatchSize target ids, so cost is O(1 + N/queryBatchSize) round-trips per
// table rather than O(N) — the whole-page read that lets a caller render every
// id's inbound `blocks` edges without a per-id fan-out.
//
// A target is matched by the coalesced target expression (DepTargetExpr) — the
// same predicate the batched source-keyed blocks/counts reads use — so an id
// that appears in any of the three typed target columns resolves; each returned

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry in a fresh transaction; the read is idempotent and the partial map is discarded.
  2. Unwrap the %w cause for timeout/network specifics and tune connection timeouts/keepalives.
  3. Reduce batch size for the ID list so each streamed result completes before timeouts hit.
Defensive patterns

Strategy: retry

Try / catch

recs, err := GetDependencyRecordsForIssuesInTx(ctx, tx, ids)
if err != nil {
    if strings.Contains(err.Error(), "get dependency records: rows:") && isTransient(err) {
        return retryWithBackoff(ctx, func() error {
            recs, err = GetDependencyRecordsForIssuesInTx(ctx, tx, ids)
            return err
        })
    }
    return err
}

Prevention

When it happens

Trigger: rows.Err() non-nil after the row loop in GetDependencyRecordsForIssuesInTx / GetDependencyRecordsForIssuesFromTableInTx — network interruption or driver read failure while streaming rows for the requested issue IDs.

Common situations: Unstable connection to a remote Dolt server during a multi-table fan-out query; server-side query timeout on large ID batches; aggressive idle timeouts killing the connection mid-result.

Related errors


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