gastownhall/beads · error

checking idx_wisps_is_blocked index: %w

Error message

checking idx_wisps_is_blocked index: %w

What it means

This wraps a failure of schemaIndexExists while checking whether `idx_wisps_is_blocked` already exists on wisps. The repair mirrors ignored migration 0006's CREATE INDEX and must inspect first to remain idempotent. The error means the index-existence query itself failed, not that the index is missing.

Source

Thrown at internal/storage/schema/migration_repairs.go:291

	hasColumn, err := schemaColumnExists(ctx, db, "wisps", "is_blocked")
	if err != nil {
		return fmt.Errorf("checking wisps.is_blocked column: %w", err)
	}
	if hasColumn {
		return nil
	}
	if _, err := db.ExecContext(ctx, "ALTER TABLE wisps ADD COLUMN is_blocked TINYINT(1) NOT NULL DEFAULT 0"); err != nil {
		return fmt.Errorf("adding wisps.is_blocked: %w", err)
	}
	return nil
}

// ensureWispIsBlockedIndex is ignored/0006's CREATE INDEX statement,
// translated to Go alongside ensureWispIsBlockedColumn above.
func ensureWispIsBlockedIndex(ctx context.Context, db DBConn) error {
	hasIndex, err := schemaIndexExists(ctx, db, "wisps", "idx_wisps_is_blocked")
	if err != nil {
		return fmt.Errorf("checking idx_wisps_is_blocked index: %w", err)
	}
	if hasIndex {
		return nil
	}
	if _, err := db.ExecContext(ctx, "CREATE INDEX idx_wisps_is_blocked ON wisps(is_blocked, status)"); err != nil {
		return fmt.Errorf("creating idx_wisps_is_blocked: %w", err)
	}
	return nil
}

// wispsTableDDLForMigration0047 is 0020_create_wisps.up.sql's shape plus every
// column a main migration <=52 subsequently adds to wisps: no_history (0023)
// and started_at (0027). wisps is dolt_ignore'd (never replicated), so
// creating it here when it is missing cannot fork any synced clone: the
// table itself is always clone-local by design, and the ignored sequence's
// own guarded create (ignored/0001: CREATE a __temp__wisps, then RENAME it
// to wisps only if wisps does not already exist, else DROP the temp table)
// simply takes the DROP branch once this has run.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix the underlying cause from the wrapped error (connectivity or privileges)
  2. Grant metadata-read access (SHOW INDEX / information_schema.STATISTICS)
  3. Re-run the repair; it re-verifies each step and is safe to retry
Defensive patterns

Strategy: try-catch

Validate before calling

var n int
if err := db.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'wisps' AND index_name = 'idx_wisps_is_blocked'").Scan(&n); err != nil {
    return fmt.Errorf("cannot inspect wisps indexes: %w", err)
}

Try / catch

err := ensureWispIsBlockedForRecompute(ctx, db)
if err != nil && strings.Contains(err.Error(), "checking idx_wisps_is_blocked index") {
    db = reconnect(db)
    return ensureWispIsBlockedForRecompute(ctx, db)
}

Prevention

When it happens

Trigger: ensureWispIsBlockedForRecompute got past the table/column checks, then ensureWispIsBlockedIndex's schemaIndexExists query errors: dropped connection, missing STATISTICS/metadata privileges, or a driver-level failure enumerating indexes on wisps.

Common situations: Privilege-restricted deployment users that can ALTER but not read index metadata; long repair sequences spanning a connection idle timeout; database failover between the column check and the index check.

Related errors


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