gastownhall/beads · error
check %s for issue %q: %w
Error message
check %s for issue %q: %w
What it means
EnsureIssueIDAvailableInTx failed while counting rows for the ID in the issues or wisps tables. This is the existence-probe step of the guard; a scan/query failure means the storage backend errored, not that the ID is taken (a taken ID yields the distinct ErrAlreadyExists wrap at index 3466).
Source
Thrown at internal/storage/issueops/create_only_guard.go:27
"github.com/steveyegge/beads/internal/storage"
)
// EnsureIssueIDAvailableInTx serializes same-shard creates and rejects occupied IDs.
func EnsureIssueIDAvailableInTx(ctx context.Context, tx DBTX, id string) error {
if tx == nil {
return fmt.Errorf("ensure issue ID available: transaction is nil")
}
if id == "" {
return fmt.Errorf("ensure issue ID available: ID is empty")
}
key := issueCreateCoordinationKey(id)
if _, err := tx.ExecContext(ctx, "REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", key, strconv.FormatInt(FreshRowLock(), 10)); err != nil {
return fmt.Errorf("coordinate issue create: %w", err)
}
for _, table := range []string{"issues", "wisps"} {
var count int
if err := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM "+table+" WHERE id = ?", id).Scan(&count); err != nil {
return fmt.Errorf("check %s for issue %q: %w", table, id, err)
}
if count > 0 {
return fmt.Errorf("%w: %s", storage.ErrAlreadyExists, id)
}
}
return nil
}
func issueCreateCoordinationKey(id string) string {
sum := sha256.Sum256([]byte(id))
shard := uint16(sum[0])<<4 | uint16(sum[1])>>4
return fmt.Sprintf("issue-create/v1/%03x", shard)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped error to identify which table and what driver error occurred
- Verify the schema is current (apply pending migrations)
- Retry with a fresh transaction and healthy connection
Example fix
// before // assume table exists // after // run migrations first, then retry create in a new tx
Defensive patterns
Strategy: retry
Validate before calling
// ensure schema is migrated before issuing creates // SELECT COUNT(*) FROM issues LIMIT 1; SELECT COUNT(*) FROM wisps LIMIT 1;
Try / catch
if err := CreateIssueInTxWithResult(ctx, tx, issue); err != nil {
if strings.HasPrefix(err.Error(), "check ") {
cause := errors.Unwrap(err)
// migrate/reconnect, then retry in a new tx
}
return err
} Prevention
- Run migrations as part of deployment
- Watch for driver connectivity errors in logs
- Avoid mixing DDL and create workloads mid-flight
When it happens
Trigger: QueryRowContext("SELECT COUNT(*) FROM issues|wisps WHERE id = ?") returns a driver error — corrupted schema, missing table, connection drop mid-transaction.
Common situations: Migrations not applied (table absent); Dolt/driver-level failures during heavy concurrent imports; DB connectivity loss.
Related errors
- failed to check issue existence: %w
- query dependency sources: %w
- query dependency targets: %w
- failed to scan existing issues for prefix %q: %w
- ErrTransaction
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d761795d4dc758bb.
Report an issue: GitHub.