{"record":{"id":"56b636bcb1e6f764","repo":"gastownhall/beads","slug":"checking-wisps-is-blocked-column-w","errorCode":null,"errorMessage":"checking wisps.is_blocked column: %w","messagePattern":"checking wisps\\.is_blocked column: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_repairs.go","lineNumber":275,"sourceCode":"\thasWisps, err := schemaTableExists(ctx, db, \"wisps\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"checking wisps table: %w\", err)\n\t}\n\tif !hasWisps {\n\t\treturn nil\n\t}\n\tif err := ensureWispIsBlockedColumn(ctx, db); err != nil {\n\t\treturn err\n\t}\n\treturn ensureWispIsBlockedIndex(ctx, db)\n}\n\n// ensureWispIsBlockedColumn is ignored/0006's ADD COLUMN statement,\n// translated to Go for a clone that reached this repair without it.\nfunc ensureWispIsBlockedColumn(ctx context.Context, db DBConn) error {\n\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 {","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_repairs.go#L257-L293","documentation":"This error wraps a failure of schemaColumnExists when the repair checks whether `wisps.is_blocked` already exists before issuing its ADD COLUMN. The repair is a Go translation of ignored migration 0006 and must inspect the column to stay idempotent; a failing inspection (not a missing column) produces this message. A missing column proceeds normally to the ALTER TABLE path.","triggerScenarios":"ensureWispIsBlockedForRecompute confirmed the wisps table exists, then ensureWispIsBlockedColumn's schemaColumnExists query errors out due to driver failure, lost connection, or insufficient privileges to read column metadata.","commonSituations":"Running repairs with a migration user lacking information_schema/COLUMNS access; transient connection drops on long-running repair sequences; proxy/load-balancer terminating idle DB connections mid-repair.","solutions":["Inspect the wrapped driver error and restore DB connectivity or privileges","Grant the migration user metadata-read access (SELECT on information_schema)","Re-run the repair — it is idempotent and will re-check the column","If it persists, test the same SHOW COLUMNS FROM wisps query manually with the app's credentials"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"var n int\nif err := db.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'wisps' AND column_name = 'is_blocked'\").Scan(&n); err != nil {\n    return fmt.Errorf(\"cannot inspect wisps columns: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := ensureWispIsBlockedForRecompute(ctx, db)\nif err != nil {\n    if strings.Contains(err.Error(), \"checking wisps.is_blocked column\") {\n        // introspection failed — reconnect and retry once\n        db = reconnect(db)\n        err = ensureWispIsBlockedForRecompute(ctx, db)\n    }\n    return err\n}","preventionTips":["Grant the repair user metadata-read privileges (SHOW COLUMNS)","Prefer running repairs on a local/stable connection to the clone","Re-run repairs on failure; column checks are idempotent","Test repairs in CI against a fresh clone to catch privilege gaps early"],"tags":["database","schema-migration","mysql","introspection"],"backgroundTag":"schema-introspection-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}