gastownhall/beads · error

get blocked-by info from %s: %w

Error message

get blocked-by info from %s: %w

What it means

Returned by queryBlockedByInfo (used by GetBlockingInfoForIssuesInTx) when the blocked-by SELECT against a dependency table fails at QueryContext time and the table is not an optional missing one. The %s names the failing table (dependencies or wisp_dependencies); %w wraps the driver error.

Source

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

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

		// Query: "blocked by" — deps where issue_id is in our set.
		//nolint:gosec // G201: depTable is a caller-controlled constant.
		blockedByQuery := fmt.Sprintf(`
			SELECT d.issue_id, %s AS depends_on_id, d.type
			FROM %s d
			WHERE d.issue_id IN (%s) AND d.type IN ('blocks', 'parent-child')
		`, depTargetExpr("d"), depTable, inClause)

		rows, err := tx.QueryContext(ctx, blockedByQuery, args...)
		if err != nil {
			if optionalBlockedTable(depTable) && isTableNotExistError(err) {
				continue
			}
			return fmt.Errorf("get blocked-by info from %s: %w", depTable, err)
		}
		var depRows []blockingInfoRow
		var blockerIDs []string
		for rows.Next() {
			var row blockingInfoRow
			if scanErr := rows.Scan(&row.issueID, &row.blockerID, &row.depType); scanErr != nil {
				_ = rows.Close()
				return fmt.Errorf("get blocking info: scan blocked-by: %w", scanErr)
			}
			depRows = append(depRows, row)
			blockerIDs = append(blockerIDs, row.blockerID)
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return fmt.Errorf("get blocking info: blocked-by rows: %w", err)
		}

		statusByID, err := loadStatusByIDInTx(ctx, tx, blockerIDs)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Examine the wrapped driver error to classify it (missing table vs permissions vs connection).
  2. If the table is missing, run database initialization/migration so dependencies exists.
  3. If permission denied, grant SELECT on the dependency tables to the connecting user.
  4. If connection-related, verify the remote server is up and connection settings are correct.
  5. Ensure client and server versions are compatible if the query itself is rejected.

Example fix

// before: legacy DB without dependencies table
// (bd fails: no such table: dependencies)

// after: migrate to current schema
bd doctor   // diagnose
bd migrate  // or re-init to create dependencies table
Defensive patterns

Strategy: validation

Validate before calling

// Go: ensure the non-optional dependencies table exists
var n int
if err := tx.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_NAME = 'dependencies'").Scan(&n); err != nil {
    return err
}
if n == 0 {
    return fmt.Errorf("dependencies table missing; run bd migrate")
}

Type guard

func isBlockedByTableError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "get blocked-by info from")
}

Try / catch

blockedBy, blocks, parents, err := GetBlockingInfoForIssuesInTx(ctx, tx, ids)
if err != nil && isBlockedByTableError(err) {
    if strings.Contains(fmt.Sprint(errors.Unwrap(err)), "no such table") {
        return runMigrations(ctx, tx) // then retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetBlockingInfoForIssuesInTx when the dependencies table does not exist (fresh/corrupt DB — wisp_dependencies absence is tolerated, dependencies is not), SELECT permission is missing, the query fails against the backend dialect, or the connection is dead.

Common situations: Unmigrated/legacy database lacking the dependencies table; DB user lacking grants; Dolt server version mismatch; network failure to a remote backend.

Related errors


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