{"record":{"id":"c356c838b4fd6268","repo":"gastownhall/beads","slug":"reading-pre-migration-dirty-table-diffs-w","errorCode":null,"errorMessage":"reading pre-migration dirty table diffs: %w","messagePattern":"reading pre-migration dirty table diffs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/schema.go","lineNumber":644,"sourceCode":"\t// from the changed-signature guard (the resumed rekey is about to change\n\t// them) and lets stageSchemaTables commit them with the rest of the pass.\n\tif resuming, err := anyAuxRekeyResumePending(ctx, db); err != nil {\n\t\treturn 0, fmt.Errorf(\"reading aux rekey sentinel: %w\", err)\n\t} else if resuming {\n\t\tfor _, t := range auxRekeyTables {\n\t\t\tdelete(dirtyBefore, t.name)\n\t\t}\n\t}\n\ttouchedDirtyTables, err := mainSource.pendingMigrationDirtyTables(ctx, db, dirtyBefore)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"checking dirty tables against pending migrations: %w\", err)\n\t}\n\tif len(touchedDirtyTables) > 0 {\n\t\treturn 0, &DirtyTablesError{Tables: touchedDirtyTables}\n\t}\n\tdirtyBeforeSignatures, err := dirtyTableSignatures(ctx, db, dirtyBefore)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"reading pre-migration dirty table diffs: %w\", err)\n\t}\n\t// Captured before the main migrations run: the aux re-key uses it to\n\t// distinguish the lineage's first rekey-aware migration (run the pass)\n\t// from a fresh clone of an already-converged lineage (record the marker\n\t// only, bd-578h9.4).\n\tmainVersionBefore, err := mainSource.currentVersion(ctx, db)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"reading pre-migration schema version: %w\", err)\n\t}\n\n\tapplied, mainColumnAdded, err := mainSource.migrate(ctx, db, 0)\n\tif err != nil {\n\t\treturn applied, err\n\t}\n\n\tbackfilled, err := ensureBackfilledCustomStatusesCustomTypes(ctx, db)\n\tif err != nil {\n\t\treturn applied, fmt.Errorf(\"backfill custom tables: %w\", err)","sourceCodeStart":626,"sourceCodeEnd":662,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/schema.go#L626-L662","documentation":"This error wraps a failure in dirtyTableSignatures, which captures pre-migration diffs (signatures) of dirty tables so MigrateUp can later prove those tables were not modified by the migration pass. If signatures cannot be read, the safety contract of #4566 (clean working set after an interrupted pass) cannot be enforced, so the migration aborts before applying anything.","triggerScenarios":"Calling MigrateUp/MigrateUpWithLock when dirtyTableSignatures errors - e.g. dolt_diff/status queries on one of the pre-existing dirty tables fail, or a dirty table was dropped/renamed between the status read and this call.","commonSituations":"Concurrent writers mutating the working set between the two pre-flight reads; corrupt diff history on a dirty table; a table listed dirty earlier but now inaccessible.","solutions":["Resolve the wrapped cause (failing diff/status query) shown after this message","Stop concurrent writers to the repository before running migrations","Commit or revert pre-existing working-set changes so there are no dirty tables to signature","Restore the table or database from a Dolt commit if diff data is corrupt"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Ensure no concurrent writers before migrating\nif locked, _ := tryLock(ctx, db); !locked {\n    return errors.New(\"another writer holds the migration lock\")\n}","typeGuard":"func isSignatureReadErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"reading pre-migration dirty table diffs\")\n}","tryCatchPattern":"applied, err := schema.MigrateUp(ctx, db)\nif isSignatureReadErr(err) {\n    // transient diff-read failure: safe to retry, nothing was applied yet\n    return retryMigrateUp(ctx, db)\n}","preventionTips":["Use MigrateUpWithLock to serialize against other writers","Avoid long-lived open transactions on the same repo during bd open","Keep Dolt diff history healthy (regular commits, no forced truncation)"],"tags":["database","migration","dolt","dirty-tables","diff"],"backgroundTag":"migration-dirty-table-conflict","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}