{"record":{"id":"c1682aac64f5bd2d","repo":"gastownhall/beads","slug":"reading-pending-ignored-migrations-w","errorCode":null,"errorMessage":"reading pending ignored migrations: %w","messagePattern":"reading pending ignored migrations: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/aux_row_id_backfill.go","lineNumber":197,"sourceCode":"// legacy clones that migrated independently hold the same logical rows under\n// different keys and their merges duplicate or refuse. This rewrites every\n// row's id to the deterministic content-derived value (internal/storage/rowid)\n// so independently-upgraded clones converge to byte-identical tables.\n//\n// It runs from MigrateUp after the schema migrations, gated on the clone-local\n// marker (see auxRowRekeyMarkerVersion): once per clone, not on every later\n// migration pass — rows inserted after the pass carry ids that are random but\n// already consistent across clones (minted once, then merged), so re-keying\n// them would churn synced tables for no convergence benefit. Changes are\n// staged and committed by MigrateUp like any other backfill.\n//\n// mainVersionBefore is the main-source cursor as it stood before this pass's\n// migrations ran; at or past auxRowRekeyShippedMainVersion the rewrite is\n// skipped (see that constant).\nfunc rekeyAuxRowIDs(ctx context.Context, db DBConn, mainVersionBefore int, pass auxRekeyPass) (bool, error) {\n\tpending, err := ignoredSource.pendingVersions(ctx, db)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"reading pending ignored migrations: %w\", err)\n\t}\n\treturn rekeyAuxRowIDsPending(ctx, db, mainVersionBefore, pass, pending)\n}\n\n// rekeyAuxRowIDsAllPasses runs every convergence pass off a single read of\n// the ignored cursor.\nfunc rekeyAuxRowIDsAllPasses(ctx context.Context, db DBConn, mainVersionBefore int) (bool, error) {\n\tpending, err := ignoredSource.pendingVersions(ctx, db)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"reading pending ignored migrations: %w\", err)\n\t}\n\twrote := false\n\tfor _, pass := range auxRekeyPasses {\n\t\tw, err := rekeyAuxRowIDsPending(ctx, db, mainVersionBefore, pass, pending)\n\t\twrote = wrote || w\n\t\tif err != nil {\n\t\t\treturn wrote, err\n\t\t}","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/aux_row_id_backfill.go#L179-L215","documentation":"rekeyAuxRowIDs gates the aux-row rekey pass on the clone-local (dolt-ignored) migration cursor by calling ignoredSource.pendingVersions. This error wraps any failure reading that cursor, meaning the pass cannot determine whether its marker migration is still pending and therefore cannot safely decide to run or skip the id rewrite.","triggerScenarios":"MigrateUp-triggered convergence where the query backing ignoredSource.pendingVersions fails — connection drop, the ignored-migrations cursor table missing or unreadable, permissions, or a locked database.","commonSituations":"Running `bd migrate`/startup against a Dolt database mid-replication; a clone whose dolt-ignored migration tables were deleted by hand; concurrent MigrateUp from two processes on the same clone.","solutions":["Unwrap to the driver error: verify database connectivity and retry — reading the cursor is safe to repeat.","Check that the clone's ignored migration tables exist (run bd doctor or the EnsureIgnoredTables path).","Ensure only one migration runs at a time on the clone (no concurrent bd processes).","If the cursor table is corrupted, restore from the Dolt history (`bd dolt pull` / dolt reset to a known-good commit)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"var n int\nif err := db.QueryRowContext(ctx, \"SELECT 1\").Scan(&n); err != nil {\n    return fmt.Errorf(\"database unreachable before migration: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := migrateUp(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"reading pending ignored migrations\") {\n        // read-only probe failed; safe to retry after connectivity is restored\n        time.Sleep(backoff)\n        return migrateUp(ctx, db)\n    }\n    return err\n}","preventionTips":["Check database connectivity before invoking MigrateUp.","Serialize migrations — never run two bd migrate processes on one clone.","Do not hand-edit or delete the ignored migration cursor tables.","Keep the clone synced (`bd dolt pull`) so cursor tables exist and are current."],"tags":["database","migration","dolt","cursor"],"backgroundTag":"migration-cursor-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}