{"record":{"id":"f8fa56e0a0bcd936","repo":"gastownhall/beads","slug":"checking-idx-wisps-is-blocked-index-w","errorCode":null,"errorMessage":"checking idx_wisps_is_blocked index: %w","messagePattern":"checking idx_wisps_is_blocked index: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_repairs.go","lineNumber":291,"sourceCode":"\thasColumn, err := schemaColumnExists(ctx, db, \"wisps\", \"is_blocked\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"checking wisps.is_blocked column: %w\", err)\n\t}\n\tif hasColumn {\n\t\treturn nil\n\t}\n\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisps ADD COLUMN is_blocked TINYINT(1) NOT NULL DEFAULT 0\"); err != nil {\n\t\treturn fmt.Errorf(\"adding wisps.is_blocked: %w\", err)\n\t}\n\treturn nil\n}\n\n// ensureWispIsBlockedIndex is ignored/0006's CREATE INDEX statement,\n// translated to Go alongside ensureWispIsBlockedColumn above.\nfunc ensureWispIsBlockedIndex(ctx context.Context, db DBConn) error {\n\thasIndex, err := schemaIndexExists(ctx, db, \"wisps\", \"idx_wisps_is_blocked\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"checking idx_wisps_is_blocked index: %w\", err)\n\t}\n\tif hasIndex {\n\t\treturn nil\n\t}\n\tif _, err := db.ExecContext(ctx, \"CREATE INDEX idx_wisps_is_blocked ON wisps(is_blocked, status)\"); err != nil {\n\t\treturn fmt.Errorf(\"creating idx_wisps_is_blocked: %w\", err)\n\t}\n\treturn nil\n}\n\n// wispsTableDDLForMigration0047 is 0020_create_wisps.up.sql's shape plus every\n// column a main migration <=52 subsequently adds to wisps: no_history (0023)\n// and started_at (0027). wisps is dolt_ignore'd (never replicated), so\n// creating it here when it is missing cannot fork any synced clone: the\n// table itself is always clone-local by design, and the ignored sequence's\n// own guarded create (ignored/0001: CREATE a __temp__wisps, then RENAME it\n// to wisps only if wisps does not already exist, else DROP the temp table)\n// simply takes the DROP branch once this has run.","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_repairs.go#L273-L309","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the underlying cause from the wrapped error (connectivity or privileges)","Grant metadata-read access (SHOW INDEX / information_schema.STATISTICS)","Re-run the repair; it re-verifies each step and is safe to retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"var n int\nif err := db.QueryRowContext(ctx,\n    \"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 {\n    return fmt.Errorf(\"cannot inspect wisps indexes: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := ensureWispIsBlockedForRecompute(ctx, db)\nif err != nil && strings.Contains(err.Error(), \"checking idx_wisps_is_blocked index\") {\n    db = reconnect(db)\n    return ensureWispIsBlockedForRecompute(ctx, db)\n}","preventionTips":["Grant STATISTICS/metadata read access to the repair user","Keep the repair connection alive (heartbeat or keepalive DSN params)","Retry the repair; index existence is re-checked each run","Verify SHOW INDEX works manually with app credentials before deploying"],"tags":["database","schema-migration","mysql","introspection","index"],"backgroundTag":"schema-introspection-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}