{"record":{"id":"bd7a45a9c9f51135","repo":"gastownhall/beads","slug":"restoring-pre-0041-nonlocal-rows-w","errorCode":null,"errorMessage":"restoring pre-0041 nonlocal rows: %w","messagePattern":"restoring pre-0041 nonlocal rows: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_repairs.go","lineNumber":152,"sourceCode":"// its shipped body can replay. 0041 begins by clearing dolt_nonlocal_tables and\n// committing (\"disable nonlocal tables for fk migrations\"). If a transient\n// interrupts 0041 after that commit but before its version row records, the\n// retry re-runs 0041 against an already-empty table: the DELETE stages nothing\n// and the paired DOLT_COMMIT (no --skip-empty in the shipped bytes) fails with\n// \"nothing to commit\". Restore the pre-0041 invariant — the four rows 0040\n// leaves — so the frozen DELETE+COMMIT has a real diff again. No-op when those\n// rows are already present (the common path).\nfunc repairPartial0041NonlocalDelete(ctx context.Context, db DBConn) error {\n\tpresent, err := anyNonlocalFrozenRowPresent(ctx, db)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif present {\n\t\treturn nil\n\t}\n\tif _, err := db.ExecContext(ctx,\n\t\t\"INSERT IGNORE INTO dolt_nonlocal_tables (table_name, target_ref, options) VALUES \"+nonlocalFrozenRowsValues); err != nil {\n\t\treturn fmt.Errorf(\"restoring pre-0041 nonlocal rows: %w\", err)\n\t}\n\tif err := commitNonlocalRepair(ctx, db,\n\t\t\"repair: restore pre-0041 nonlocal rows before replay\"); err != nil {\n\t\treturn fmt.Errorf(\"committing 0041 nonlocal repair: %w\", err)\n\t}\n\treturn nil\n}\n\n// ensureWispTablesForMixedBlockedRecompute repairs #4695 (and the identical\n// #4176 clone-skew shape): migration 0047's final recompute block joins\n// wisps/wisp_dependencies unconditionally in a WITH RECURSIVE UPDATE. Those\n// tables are dolt_ignore'd (0019_wisps_dolt_ignore,\n// 0040_ignored_tables_also_nonlocal_tables), so they never sync to a clone,\n// and MigrateUp runs the main sequence (which reaches 0047) before the\n// ignored sequence that (re)creates them locally. Any clone whose\n// schema_migrations cursor arrives below the binary's latest -- the normal\n// window right after a schema bump, before every producer has re-pushed, and\n// also how a pre-1.0 database's stale cursor numbering can treat the main","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_repairs.go#L134-L170","documentation":"repairPartial0041NonlocalDelete restores the four pre-0041 dolt_nonlocal_tables rows with INSERT IGNORE so shipped 0041's DELETE+COMMIT has a real diff (its own commit lacks --skip-empty and fails with \"nothing to commit\" on an already-empty table). This error wraps failure of that INSERT — connection drop, table missing, or a column-shape mismatch on a drifted database.","triggerScenarios":"bd init re-running 0041 after a transient interrupted it post-clear-commit but pre-version-record; the INSERT IGNORE of wisps/wisp_*/repo_mtimes/local_metadata rows fails (connection drop, table absent, or drifted column set).","commonSituations":"Interrupted upgrade against a shared Dolt sql-server; drifted clone where dolt_nonlocal_tables lacks the (table_name, target_ref, options) shape; concurrent access during repair.","solutions":["Retry bd init — the repair is idempotent and guarded by row presence","Verify dolt_nonlocal_tables has table_name/target_ref/options columns; a drifted shape needs manual schema repair","Ensure exclusive access to the database during init","Check connectivity and inspect the wrapped error for the SQL cause"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// check the table shape matches what the repair inserts\nvar n int\ndb.QueryRowContext(ctx, `SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS\n  WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dolt_nonlocal_tables'\n  AND COLUMN_NAME IN ('table_name','target_ref','options')`).Scan(&n)\n// n must be 3 before INSERT IGNORE ... (table_name, target_ref, options) can succeed","typeGuard":null,"tryCatchPattern":"if err := repairPartial0041NonlocalDelete(ctx, db); err != nil {\n    if isTransient(err) {\n        return repairPartial0041NonlocalDelete(ctx, db) // guarded, idempotent\n    }\n    return fmt.Errorf(\"0041 repair failed: %w\", err)\n}","preventionTips":["Retry init — the restore is INSERT IGNORE and guarded by row presence","Verify dolt_nonlocal_tables column shape on drifted databases before upgrading","Run migrations with a stable connection and exclusive access","Back up before upgrading databases with nonstandard history"],"tags":["dolt","migration","storage","transient"],"backgroundTag":"migration-partial-apply","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}