gastownhall/beads · error
check remaining blockers from %s: %w
Error message
check remaining blockers from %s: %w
What it means
Wraps a SQL failure from querying a dependency table for remaining 'blocks' edges while computing newly-unblocked issues inside GetNewlyUnblockedByCloseInTx. The table name is embedded in the message so you know which dependency table (deps or deps_v2 style optional table) failed. It is thrown whenever tx.QueryContext returns an error that is not an ignorable missing-optional-table error, aborting the unblock computation and the surrounding transaction.
Source
Thrown at internal/storage/issueops/dependency_queries.go:850
if end > len(candidateIDs) {
end = len(candidateIDs)
}
batch := candidateIDs[start:end]
placeholders, batchArgs := buildSQLInClause(batch)
remainingByCandidate := make(map[string][]string, len(batch))
remainingBlockerSet := make(map[string]struct{})
for _, depTable := range []string{"dependencies", "wisp_dependencies"} {
//nolint:gosec // G201: depTable is hardcoded.
depRows, err := tx.QueryContext(ctx, fmt.Sprintf(`
SELECT issue_id, %s AS depends_on_id FROM %s
WHERE issue_id IN (%s) AND type = 'blocks' AND %s != ?
`, DepTargetExpr, depTable, placeholders, DepTargetExpr), append(batchArgs, closedIssueID)...)
if err != nil {
if optionalBlockedTable(depTable) && isTableNotExistError(err) {
continue
}
return nil, fmt.Errorf("check remaining blockers from %s: %w", depTable, err)
}
for depRows.Next() {
var candidateID, blockerID string
if err := depRows.Scan(&candidateID, &blockerID); err != nil {
_ = depRows.Close()
return nil, fmt.Errorf("scan remaining blocker: %w", err)
}
remainingByCandidate[candidateID] = append(remainingByCandidate[candidateID], blockerID)
remainingBlockerSet[blockerID] = struct{}{}
}
_ = depRows.Close()
if err := depRows.Err(); err != nil {
return nil, fmt.Errorf("remaining blocker rows from %s: %w", depTable, err)
}
}
remainingBlockerIDs := make([]string, 0, len(remainingBlockerSet))
for blockerID := range remainingBlockerSet {View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped underlying error (%w) to identify the driver error code
- Verify the dependency table schema matches what this version of beads expects (run migrations/bd migrate)
- If the table is optional, confirm isTableNotExistError matched; if not, the table exists but is broken — inspect/repair it
- Retry the operation after resolving any transient lock or connection issue
Example fix
// before
rows, err := tx.QueryContext(ctx, q, args...)
if err != nil { return nil, err } // loses table context
// after
if err != nil {
if optionalBlockedTable(depTable) && isTableNotExistError(err) { continue }
return nil, fmt.Errorf("check remaining blockers from %s: %w", depTable, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// before calling close/unblock flows
if err := bd.Doctor(ctx); err != nil { /* fix schema/storage first */ }
_ = db.QueryRow("SELECT COUNT(*) FROM deps").Scan(&n) // table must be queryable Try / catch
err := tx.CloseIssue(ctx, id)
if err != nil {
var wrapped interface{ Unwrap() error }
if errors.Is(err, context.DeadlineExceeded) { /* retry */ }
log.Fatalf("unblock check failed: %v", err)
} Prevention
- Keep beads upgraded so migrations run before queries
- Run `bd doctor` after version upgrades to validate storage schema
- Avoid concurrent DDL while bd commands are running
- Back up the database before manual schema edits
When it happens
Trigger: Calling GetNewlyUnblockedByCloseInTx after closing an issue when the SQL SELECT against one of the dependency tables fails: malformed schema, corrupted table, lock timeout, or driver-level query error other than table-not-exist on an optional table.
Common situations: Partial or failed migrations leaving a dependency table in a bad state; database file corruption in embedded Dolt/SQLite deployments; concurrent DDL during the transaction; permission errors on the dep table.
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
- count inbound dependencies from %s: %w
- no store is open for this workspace
- load dependency records: %w
- failed to remove relates-to %s -> %s: %w
- failed to get dependencies for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c9ecc0d42b3823c2.
Report an issue: GitHub.