{"record":{"id":"02d3c4d61ebaa684","repo":"gastownhall/beads","slug":"failed-to-begin-transaction-w-02d3c4","errorCode":null,"errorMessage":"failed to begin transaction: %w","messagePattern":"failed to begin transaction: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/fix/dep_keys.go","lineNumber":116,"sourceCode":"\n// repairDependencyKeys scans and repairs rekey-backfill leftovers on an open\n// connection. Split from DependencyKeys so the repair logic is testable\n// against an existing store handle.\nfunc repairDependencyKeys(ctx context.Context, db *sql.DB, verbose bool) error {\n\tanomalies, err := ScanDependencyKeys(ctx, db)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to scan dependency keys: %w\", err)\n\t}\n\tif len(anomalies) == 0 {\n\t\tfmt.Println(\"  No dependency key anomalies to fix\")\n\t\treturn nil\n\t}\n\n\t// Uses explicit transaction so writes persist when @@autocommit is OFF\n\t// (e.g. Dolt server started with --no-auto-commit).\n\ttx, err := db.Begin()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to begin transaction: %w\", err)\n\t}\n\tvar rekeyed, removed, failed int\n\trepairedTables := make(map[string]bool)\n\tfor _, a := range anomalies {\n\t\tshowIndividual := verbose || len(a.MisKeyed)+len(a.NullTarget) < 20\n\t\tfor _, mk := range a.MisKeyed {\n\t\t\t//nolint:gosec // G201: table is a hardcoded constant, never user input.\n\t\t\tif _, err := tx.Exec(fmt.Sprintf(`UPDATE %s SET id = ? WHERE id = ?`, a.Table), mk[1], mk[0]); err != nil {\n\t\t\t\tfmt.Printf(\"  Warning: failed to re-key %s row %s (row keeps its old id): %v\\n\", a.Table, mk[0], err)\n\t\t\t\tfailed++\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trekeyed++\n\t\t\trepairedTables[a.Table] = true\n\t\t\tif showIndividual {\n\t\t\t\tfmt.Printf(\"  Re-keyed %s row %s → %s\\n\", a.Table, mk[0], mk[1])\n\t\t\t}\n\t\t}","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/fix/dep_keys.go#L98-L134","documentation":"repairDependencyKeys wraps all writes in an explicit transaction so repairs persist even when the Dolt server runs with @@autocommit OFF. If db.Begin() fails — the pool cannot obtain a usable connection or start a transaction — this error wraps that cause and the repair aborts with no changes applied.","triggerScenarios":"Calling DependencyKeys/repairDependencyKeys when db.Begin() fails: connection pool exhausted, connection dropped between scan and Begin, or the Dolt server rejecting transaction start (e.g. server shutting down, --no-auto-commit server in a bad state).","commonSituations":"Long doctor run over a flaky connection where the pool connection goes stale before Begin; Dolt server restarted mid-fix; too many concurrent bd processes holding connections.","solutions":["Retry the command — transient connection loss is the most common cause","Ensure the Dolt server is running and healthy (bd doctor / server logs)","Set reasonable pool limits/timeouts (SetMaxOpenConns, ConnMaxLifetime) so connections don't go stale"],"exampleFix":"// before\nif err := repairDependencyKeys(ctx, db, verbose); err != nil { ... } // failed to begin transaction\n// after: warm/validate the connection first\nif err := db.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"database unreachable: %w\", err)\n}\nif err := repairDependencyKeys(ctx, db, verbose); err != nil { ... }","handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"DB unreachable, refusing to begin repair transaction: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := repairDependencyKeys(ctx, db, verbose)\nif err != nil && strings.Contains(err.Error(), \"failed to begin transaction\") {\n\ttime.Sleep(2 * time.Second)\n\terr = repairDependencyKeys(ctx, db, verbose) // Begin failure = nothing written; retry safe\n}","preventionTips":["Configure the sql pool (SetConnMaxLifetime, Ping timeout) so stale connections are recycled","Avoid concurrent bd writers against the same DB during repairs","Ensure the Dolt server is fully up (health check) before running fixes"],"tags":["database","transaction","dolt","doctor"],"backgroundTag":"begin-transaction-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}