gastownhall/beads · error

get dependency counts (blockers from %s): %w

Error message

get dependency counts (blockers from %s): %w

What it means

This error wraps the failure of the per-table 'blocks' count query in GetDependencyCountsInTx — a GROUP BY issue_id COUNT over a dependency table filtered to type='blocks'. It is returned only when the table is expected to exist (optional wisp table absence is skipped via isTableNotExistError), so it signals a real query failure on a present table.

Source

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

		for i, id := range batch {
			placeholders[i] = "?"
			args[i] = id
		}
		inClause := strings.Join(placeholders, ",")

		for _, depTable := range depTables {
			//nolint:gosec // G201: depTable is hardcoded and inClause contains only ? placeholders.
			depRows, err := tx.QueryContext(ctx, fmt.Sprintf(`
				SELECT issue_id, COUNT(*) as cnt
				FROM %s
				WHERE issue_id IN (%s) AND type = 'blocks'
				GROUP BY issue_id
			`, depTable, inClause), args...)
			if err != nil {
				if optionalBlockedTable(depTable) && isTableNotExistError(err) {
					continue
				}
				return nil, fmt.Errorf("get dependency counts (blockers from %s): %w", depTable, err)
			}
			for depRows.Next() {
				var id string
				var cnt int
				if err := depRows.Scan(&id, &cnt); err != nil {
					_ = depRows.Close()
					return nil, fmt.Errorf("get dependency counts: scan blocker: %w", err)
				}
				if c, ok := result[id]; ok {
					c.DependencyCount += cnt
				}
			}
			_ = depRows.Close()
			if err := depRows.Err(); err != nil {
				return nil, fmt.Errorf("get dependency counts: blocker rows: %w", err)
			}

			//nolint:gosec // G201: depTable is hardcoded and inClause contains only ? placeholders.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error to classify the root cause (missing column vs connection vs lock).
  2. Run migrations so the table has issue_id and type columns with supporting indexes for the GROUP BY.
  3. Retry on transient errors; investigate lock holders if 'lock wait timeout' appears.
  4. Verify the driver supports the exact SQL dialect used by the counts query.
  5. If it happens only for wisp_dependencies, the missing-table skip failed — check isTableNotExistError coverage for your driver.

Example fix

// before: wisp table missing but error not recognized, so counts abort
// after: ensure migrations create the table so classification never matters
CREATE TABLE IF NOT EXISTS wisp_dependencies (id VARCHAR(64) PRIMARY KEY, issue_id VARCHAR(64) NOT NULL, ...);
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the blockers query preconditions: columns exist and table is present
rows, err := tx.QueryContext(ctx, "SELECT issue_id, type FROM dependencies WHERE type = 'blocks' LIMIT 1")
if err != nil { /* migration incomplete; hydration counts will fail */ }

Type guard

func blockersQueryReady(ctx context.Context, tx DBTX, table string) bool {
    var id string
    err := tx.QueryRowContext(ctx, "SELECT issue_id FROM "+table+" WHERE type = 'blocks' LIMIT 1").Scan(&id)
    return err == nil || isTableNotExistError(err)
}

Try / catch

counts, err := GetDependencyCountsInTx(ctx, tx, issueIDs)
if err != nil && strings.Contains(err.Error(), "blockers from ") {
    if isTableNotExistError(err) { /* wisp table edge case: verify optional-table skip */ }
    else { /* schema or connectivity problem: migrate/retry accordingly */ }
}

Prevention

When it happens

Trigger: Calling GetDependencyCountsInTx/HydrateReadyRowInTx when 'dependencies' (or a present 'wisp_dependencies') rejects the blockers query: schema drift (missing issue_id/type columns), SQL dialect incompatibility, context cancellation, connection failure, or lock contention.

Common situations: Schema drift after an aborted migration; remote database network issues during ready-row hydration; another process holding a long lock; driver version mismatch with the SQL used in the counts query.

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/c9667294feab942f. Report an issue: GitHub.