{"record":{"id":"731525056ebf6d62","repo":"gastownhall/beads","slug":"remote-migrate-gate-read-remotes-w","errorCode":null,"errorMessage":"remote-migrate gate: read remotes: %w","messagePattern":"remote-migrate gate: read remotes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/remote_migrate_gate.go","lineNumber":420,"sourceCode":"\tcurrent, err := CurrentVersion(ctx, db)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"remote-migrate gate: read current version: %w\", err)\n\t}\n\tif current == 0 {\n\t\treturn nil // fresh database — nothing to fork\n\t}\n\n\tpending, err := PendingVersions(ctx, db)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"remote-migrate gate: read pending versions: %w\", err)\n\t}\n\tif len(pending) == 0 {\n\t\treturn nil // already current — nothing to migrate\n\t}\n\n\thasRemote, err := anyDoltRemoteConfigured(ctx, db)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"remote-migrate gate: read remotes: %w\", err)\n\t}\n\t// dolt_remotes can read empty even when a remote is configured: a freshly\n\t// (auto-)started server has not yet synced CLI remotes from .dolt/config\n\t// (GH#2315). Consult the caller's on-disk probe before allowing migration.\n\tif !hasRemote && extraHasRemote != nil {\n\t\thasRemote = extraHasRemote()\n\t}\n\tif !hasRemote {\n\t\treturn nil // no remote — no cross-clone fork risk\n\t}\n\n\t// Programmatic override — set by `bd migrate --force` / `bd migrate schema\n\t// --force` in the root PersistentPreRunE before both\n\t// autoMigrateOnVersionBump and the main store open. Process-local by\n\t// design: unlike os.Setenv(AllowRemoteMigrateEnv), it cannot leak into\n\t// child processes (git hooks, dolt subprocesses). Consulted here — only\n\t// once the gate would otherwise fire — so normal opens produce no noise.\n\tif forceAllowRemoteMigrate {","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/remote_migrate_gate.go#L402-L438","documentation":"This error wraps a failure while reading the configured Dolt remotes (`dolt_remotes`) during the remote-migrate safety gate. The gate must know whether any remote is configured before allowing a destructive remote-migration flow, and this error means the remotes themselves could not be read from the database.","triggerScenarios":"Calling any of CheckRemoteMigrateGate, CheckRemoteMigrateGateWithAdopt, CheckRemoteMigrateGateWithRemoteCheck, CheckRemoteMigrateGateForRemoteWithRemoteCheck, or CheckRemoteMigrateGateForRemoteWithRemoteCheckAndAdopt when pending migrations exist and the internal `anyDoltRemoteConfigured` query against the remotes table fails (e.g. locked DB, corrupted metadata, server not ready).","commonSituations":"Dolt SQL server freshly started and not yet serving the remotes table; transient connection loss mid-gate; database corruption; running the gate concurrently with another writer holding locks.","solutions":["Check the wrapped cause (%w) — most often a transient DB/server issue; retry after confirming the Dolt server is up and responsive","Run `bd doctor` or a direct `SELECT * FROM dolt_remotes` against the database to confirm the remotes table is readable","If corruption is suspected, restore from a recent backup or re-clone the repo","File an issue if it reproduces consistently on a healthy database"],"exampleFix":"// before: gate fails with opaque wrapped error\nerr := CheckRemoteMigrateGate(ctx, db)\n// after: probe server health and retry the gate\nif err := waitForDoltServer(ctx, db); err != nil { return err }\nerr := CheckRemoteMigrateGate(ctx, db)","handlingStrategy":"retry","validationCode":"// probe that remotes are readable before running the gate\nvar n int\nif err := db.QueryRowContext(ctx, \"SELECT COUNT(*) FROM dolt_remotes\").Scan(&n); err != nil {\n\treturn fmt.Errorf(\"dolt_remotes not readable yet: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := CheckRemoteMigrateGate(ctx, db)\nif err != nil {\n\tvar retryable bool\n\tif strings.Contains(err.Error(), \"read remotes\") { retryable = true }\n\tif retryable { time.Sleep(backoff); retry() }\n}","preventionTips":["Wait for the Dolt server to be fully started before invoking remote-migrate gates (GH#2315)","Provide the on-disk extraHasRemote probe where available so a cold remotes table doesn't mislead the gate","Serialize remote-migrate flows to avoid concurrent lock contention"],"tags":["dolt","migration","gate","remotes"],"backgroundTag":"dolt-remotes-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}