gastownhall/beads · error
check remaining blocker status: %w
Error message
check remaining blocker status: %w
What it means
Wraps a failure from loadStatusByIDInTx while fetching statuses of remaining blocker issues inside GetNewlyUnblockedByCloseInTx. The dependency edges were read fine, but resolving whether each blocker is still open/closed/pinned failed, so the function cannot safely decide which candidates became unblocked.
Source
Thrown at internal/storage/issueops/dependency_queries.go:874
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 {
remainingBlockerIDs = append(remainingBlockerIDs, blockerID)
}
sort.Strings(remainingBlockerIDs)
statusByID, err := loadStatusByIDInTx(ctx, tx, remainingBlockerIDs)
if err != nil {
return nil, fmt.Errorf("check remaining blocker status: %w", err)
}
for candidateID, blockerIDs := range remainingByCandidate {
for _, blockerID := range blockerIDs {
status, ok := statusByID[blockerID]
if ok && status != types.StatusClosed && status != types.StatusPinned {
stillBlocked[candidateID] = true
break
}
}
}
}
var unblocked []*types.Issue
for _, id := range candidateIDs {
if stillBlocked[id] {
continue
}
issue, err := GetIssueInTx(ctx, tx, id)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error from loadStatusByIDInTx for the root cause
- Verify the issues table exists with the expected id/status columns
- Resolve lock contention (retry the transaction) if the error is a deadlock/timeout
- Run storage integrity checks/repairs if corruption is indicated
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure issues table is healthy
_ = db.QueryRow("SELECT COUNT(*) FROM issues WHERE status != ''").Scan(&n) Try / catch
if err := tx.CloseIssue(ctx, id); err != nil {
if strings.Contains(err.Error(), "check remaining blocker status") {
// inspect issues-table health, then retry
}
return err
} Prevention
- Keep the issues table schema current via migrations
- Limit concurrent writers to reduce lock contention
- Run bd doctor periodically on embedded databases
When it happens
Trigger: The batch status lookup for remainingBlockerIDs fails — e.g. the issues table query inside loadStatusByIDInTx errors due to schema problems, lock contention, or driver errors.
Common situations: Issues table missing or migrated to an unexpected shape; transaction deadlock/lock timeout with concurrent writers; embedded DB corruption.
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
- check blocker status: %w
- count wisp dependencies: %w
- count labels: %w
- count wisp labels: %w
- count events: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6b660514fc78128f.
Report an issue: GitHub.