{"record":{"id":"154f1f44e66869de","repo":"gastownhall/beads","slug":"dropping-idx-wisp-dep-type-target-for-the-0058-rep","errorCode":null,"errorMessage":"dropping idx_wisp_dep_type_target for the 0058 repair: %w","messagePattern":"dropping idx_wisp_dep_type_target for the 0058 repair: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/wisp_dep_forward_repair.go","lineNumber":329,"sourceCode":"//\n// The order is load-bearing in two places. idx_wisp_dep_type_target is indexed\n// on depends_on_id and must go before the column. Every foreign key must go\n// before DROP PRIMARY KEY, because the primary key is the only issue_id-leading\n// index on this shape and fk_wisp_dep_issue holds it hostage:\n//\n//\tError 1553 (HY000): can't drop index 'PRIMARY': needed in foreign key\n//\tconstraint fk_wisp_dep_issue\n//\n// Each drop is guarded on the live schema, so a resume after a crash mid-drop\n// skips what is already gone rather than failing on a missing object.\nfunc dropWispDepLegacyShape(ctx context.Context, db DBConn) error {\n\thasIndex, err := schemaIndexExists(ctx, db, wispDepTable, \"idx_wisp_dep_type_target\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif hasIndex {\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisp_dependencies DROP INDEX idx_wisp_dep_type_target\"); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping idx_wisp_dep_type_target for the 0058 repair: %w\", err)\n\t\t}\n\t}\n\n\tfor _, c := range wispDepFinalConstraints {\n\t\tif !strings.HasPrefix(c.name, \"fk_\") {\n\t\t\tcontinue\n\t\t}\n\t\tpresent, err := schemaConstraintExists(ctx, db, wispDepTable, c.name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !present {\n\t\t\tcontinue\n\t\t}\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisp_dependencies DROP FOREIGN KEY \"+c.name); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping %s for the 0058 repair: %w\", c.name, err)\n\t\t}\n\t}","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/wisp_dep_forward_repair.go#L311-L347","documentation":"Wraps a failure when dropping the legacy index idx_wisp_dep_type_target from wisp_dependencies as part of removing the pre-0058 shape. The DROP INDEX DDL failed even though schemaIndexExists confirmed the index is present. Repair aborts before the final constraints are installed.","triggerScenarios":"dropWispDepLegacyShape executes `ALTER TABLE wisp_dependencies DROP INDEX idx_wisp_dep_type_target` and the ALTER fails — missing DROP/ALTER privilege, metadata mismatch, lock contention, or the index is implicitly required by a FK not yet dropped.","commonSituations":"DB user lacking ALTER privilege on the schema; upgrade run concurrently with another migration; a foreign key still referencing the index (drop order mismatch after partial repair); Dolt storage engine rejecting the ALTER mid-transaction.","solutions":["Check the wrapped cause (%w): privilege errors → grant ALTER/DROP; lock errors → retry when idle.","Verify no leftover FK still depends on the index; if a prior repair crashed, re-run the repair so FKs are dropped first (guarded steps).","Manually verify with SHOW INDEX / SHOW CREATE TABLE, then re-run `bd` to resume the idempotent repair.","If Dolt refuses the ALTER, check Dolt version compatibility with generated-column tables and upgrade the server."],"exampleFix":"// before: ALTER fails because FK still uses the index after a crashed pass\n// after: re-run full repair (guarded) or drop dependent FK first\nif err := repairWispDependenciesForwardShape(ctx, db); err != nil {\n    log.Fatalf(\"resume repair after verifying FK state: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// verify index state and permissions before running the repair\n_, err := db.ExecContext(ctx, \"SHOW INDEX FROM wisp_dependencies WHERE Key_name = 'idx_wisp_dep_type_target'\")\nif err != nil { log.Fatalf(\"cannot inspect index metadata: %v\", err) }\n_, err = db.ExecContext(ctx, \"SHOW CREATE TABLE wisp_dependencies\")\nif err != nil { log.Fatalf(\"migration user lacks metadata/ALTER rights: %v\", err) }","typeGuard":null,"tryCatchPattern":"if err := repairWispDependenciesForwardShape(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"dropping idx_wisp_dep_type_target\") {\n        // inspect SHOW CREATE TABLE for leftover FKs relying on the index\n        return fmt.Errorf(\"repair blocked on legacy index; clear dependent FKs and re-run: %w\", err)\n    }\n    return err\n}","preventionTips":["Grant ALTER/DROP to the migration user.","Let the guarded repair drop FKs before indexes — never hand-drop pieces.","Keep Dolt server at a version supporting the 0058 shape changes.","Verify no crashed prior repair left half-dropped structures (SHOW CREATE TABLE)."],"tags":["database","schema-repair","migration","ddl"],"backgroundTag":"schema-migration-ddl-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}