gastownhall/beads · error

get dependent records: rows: %w

Error message

get dependent records: rows: %w

What it means

This error wraps rows.Err() after iterating dependent dependency rows — a deferred/iterative error that occurred while fetching result rows (e.g. the connection died mid-iteration). It is distinct from the initial query error and from per-row scan errors.

Source

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

			return fmt.Errorf("get dependent records from %s: %w", depTable, err)
		}
		for rows.Next() {
			dep, scanErr := scanDependentRow(rows)
			if scanErr != nil {
				_ = rows.Close()
				return fmt.Errorf("get dependent records: scan: %w", scanErr)
			}
			// De-dup by row id (depid): the wisp copy of a promoted edge carries
			// the same id as the durable copy scanned first, so skip the repeat.
			if seen[dep.ID] {
				continue
			}
			seen[dep.ID] = true
			result[dep.DependsOnID] = append(result[dep.DependsOnID], dep)
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("get dependent records: rows: %w", err)
		}
	}
	return nil
}

// Target-keyed dependents-read bounds. A raw read has no consumer to apply a
// page size, so it clamps its own (default when limit <= 0, hard cap otherwise).
const (
	defaultDependentRecordsLimit = 100
	maxDependentRecordsLimit     = 500
)

// GetDependentRecordsInTx returns raw dependency rows whose TARGET is targetID
// — the edges pointing AT targetID — from both the permanent and wisp
// dependency tables. Unlike GetDependents/GetDependentsWithMetadata it does
// NOT join or hydrate the source issues, so edges from dangling, cross-project,
// or wisp sources are returned as raw rows rather than dropped. RAW READ: it
// spans BOTH the `dependencies` and `wisp_dependencies` tables and applies no

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped driver error — it is almost always connection- or context-related and often transient.
  2. Retry the read; these errors rarely indicate data problems.
  3. Reduce batch work per transaction or raise connection idle/read timeouts.
  4. Enable keepalives or connection health checks on the driver DSN.
  5. Ensure the context passed in has adequate deadline for large result sets.

Example fix

// before: single-shot read with a short deadline
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
deps, err := GetDependentRecordsForIssuesInTx(ctx, tx, ids)
// after: deadline sized to the workload, retry on transient rows errors
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
deps, err := GetDependentRecordsForIssuesInTx(ctx, tx, ids)
if err != nil && isTransientNetError(err) { deps, err = GetDependentRecordsForIssuesInTx(ctx, tx, ids) }
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm the connection is alive before long batch reads
if err := tx.QueryRowContext(ctx, "SELECT 1").Scan(&one); err != nil {
    return fmt.Errorf("connection unhealthy before dependent-records read: %w", err)
}

Type guard

func isTransientRowError(err error) bool {
    if err == nil { return false }
    msg := err.Error()
    return strings.Contains(msg, "connection") || strings.Contains(msg, "bad connection") || errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
}

Try / catch

err := getDependentRecordsIntoFromTable(ctx, tx, table, ids, seen, result)
if err != nil && strings.Contains(err.Error(), "rows: ") && isTransientRowError(err) {
    err = retryWithBackoff(3, func() error { return getDependentRecordsIntoFromTable(ctx, tx, table, ids, seen, result) })
}

Prevention

When it happens

Trigger: Calling GetDependentRecordsForIssuesInTx when the database connection drops or the context is canceled while streaming rows between rows.Next() calls, or a driver-level protocol error occurs during row retrieval.

Common situations: Long-running batched reads over many target IDs hitting a connection idle timeout; network flakiness to a remote Dolt/MySQL server; server-side kill of a long query.

Related errors


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