{"record":{"id":"7b1613a2d126e35f","repo":"gastownhall/beads","slug":"reading-aux-rekey-sentinel-w-7b1613","errorCode":null,"errorMessage":"reading aux rekey sentinel: %w","messagePattern":"reading aux rekey sentinel: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/schema.go","lineNumber":629,"sourceCode":"\t// (so nothing else rides into the commit) and before the first step runs.\n\tif seedChanged {\n\t\tif err := commitSeededDoltIgnore(ctx, db); err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\tdirtyBefore, err := committableDirtyTables(ctx, db)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"reading pre-migration status: %w\", err)\n\t}\n\tdelete(dirtyBefore, \"dolt_ignore\")\n\t// A previous pass that crashed mid-aux-rekey left its partial UPDATEs\n\t// dirty in the working set with the in-progress sentinel still recorded\n\t// (bd-578h9.16). Those tables are this pass's own migration state, not\n\t// pre-existing user writes: dropping them from dirtyBefore exempts them\n\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)","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/schema.go#L611-L647","documentation":"This error wraps a failure while reading the aux-rekey resume sentinel (anyAuxRekeyResumePending) during MigrateUp. The sentinel records whether a previous migration pass crashed mid aux-row rekey; MigrateUp needs it to decide which dirty tables to exempt from its guards. If the sentinel cannot be read, the migration aborts rather than risk misclassifying pre-existing dirty tables.","triggerScenarios":"Calling MigrateUp (directly or via MigrateUpWithLock) on a database where the query that reads the aux rekey in-progress marker fails - e.g. the marker storage table/system doc is unreadable, corrupt, or the Dolt connection errors mid-read.","commonSituations":"Resuming after a crashed migration pass (bd-578h9.16 scenario) where the marker table itself is damaged; a partially copied database missing the sentinel storage; storage engine errors during the read.","solutions":["Fix the wrapped cause returned after this message (query/IO error reading the sentinel)","Verify the marker/ignored-schema-migrations storage exists and is readable in this clone","If the database is a broken partial copy, re-clone or restore from a good commit and re-run migrations","Re-run MigrateUp once storage access is healthy; the sentinel read is retried on each pass"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify marker storage is readable before migrating\nif _, err := db.QueryContext(ctx,\n    \"SELECT * FROM ignored_schema_migrations LIMIT 1\"); err != nil {\n    return fmt.Errorf(\"ignored migration marker unreadable: %w\", err)\n}","typeGuard":"func isAuxRekeySentinelErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"reading aux rekey sentinel\")\n}","tryCatchPattern":"if _, err := schema.MigrateUp(ctx, db); err != nil {\n    if isAuxRekeySentinelErr(err) {\n        return fmt.Errorf(\"cannot determine crash-recovery state: %w\", err)\n    }\n    return err\n}","preventionTips":["Let MigrateUp own all crash-recovery markers; never delete internal marker rows","After a killed migration, simply re-run MigrateUp rather than repairing tables by hand","Keep dolt_ignore'd internal tables intact in any clone/copy operation"],"tags":["database","migration","dolt","rekey","sentinel"],"backgroundTag":"migration-precheck-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}