gastownhall/beads · error

get dependency counts: scan blocker: %w

Error message

get dependency counts: scan blocker: %w

What it means

This error is returned by GetDependencyCountsInTx when an SQL row returned by the 'blocked-by counts' aggregate query (SELECT issue_id, COUNT(*) FROM <dep table> WHERE issue_id IN (...) AND type='blocks' GROUP BY issue_id) cannot be scanned into (string, int). The %w wraps the underlying driver scan error. It means the driver returned a row whose column count or types do not match the two expected columns.

Source

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

			//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.
			blockingRows, err := tx.QueryContext(ctx, fmt.Sprintf(`
				SELECT %s AS depends_on_id, COUNT(*) as cnt
				FROM %s
				WHERE %s AND type = 'blocks'
				GROUP BY %s
			`, DepTargetExpr, depTable, depTargetIn("", inClause), DepTargetExpr), args...)
			if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped driver error (%w) for the exact column/type mismatch and fix the offending row or column type in dependencies/wisp_dependencies.
  2. Verify the database schema matches the version of the library: run bd doctor / schema migration to align dependencies table columns (issue_id non-null, integer count).
  3. If rows were hand-edited, remove or repair rows with NULL or non-string issue_id values.
  4. If using a remote Dolt backend, confirm client and server versions are compatible; upgrade or downgrade to matching versions.
  5. As a workaround, recompute counts via bd doctor rebuild or re-sync from remote to restore a consistent schema.

Example fix

// before: hand-migrated table with NULLable issue_id
ALTER TABLE dependencies MODIFY issue_id VARCHAR(50) NULL;

// after: restore expected non-null schema so Scan succeeds
ALTER TABLE dependencies MODIFY issue_id VARCHAR(50) NOT NULL;
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: verify expected schema before calling
var cols []struct {
    Field  string
    Type   string
    Null   string
}
if err := db.Select(&cols,
    "SELECT COLUMN_NAME AS Field, DATA_TYPE AS Type, IS_NULLABLE AS Null FROM information_schema.COLUMNS WHERE TABLE_NAME = 'dependencies'"); err != nil {
    return err
}
for _, c := range cols {
    if c.Field == "issue_id" && c.Null == "YES" {
        return fmt.Errorf("dependencies.issue_id must be NOT NULL")
    }
}

Type guard

func isScanError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "get dependency counts: scan blocker")
}

Try / catch

counts, err := GetDependencyCountsInTx(ctx, tx, ids)
if err != nil {
    var scanErr *fmt.ScanError // inspect wrapped driver error
    if strings.Contains(err.Error(), "scan blocker") {
        // schema drift: run migration/doctor before retrying
        return fmt.Errorf("schema mismatch: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetDependencyCountsInTx (directly or via HydrateReadyRowInTx) against a database whose dependencies/wisp_dependencies schema is non-standard — e.g. issue_id or the COUNT column is NULLable/null, has a different type (TEXT vs VARCHAR fine, but BLOB or NULL fails), or the table was migrated to a different column layout while the binary expects issue_id, count.

Common situations: Running a newer beads binary against an older database (or vice versa) after a schema change; a corrupted/partially-migrated Dolt database; custom replicas with altered column types; NULL issue_id values injected by manual SQL edits.

Related errors


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