{"record":{"id":"73ae7bf1b5d86b86","repo":"gastownhall/beads","slug":"failed-to-begin-regular-tx-w","errorCode":null,"errorMessage":"failed to begin regular tx: %w","messagePattern":"failed to begin regular tx: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/transaction.go","lineNumber":196,"sourceCode":"\t\t\tdoltMetrics.poolWaitCount.Add(ctx, statsAfter.WaitCount-statsBefore.WaitCount)\n\t\t\twaitMs := float64(statsAfter.WaitDuration-statsBefore.WaitDuration) / float64(time.Millisecond)\n\t\t\tdoltMetrics.poolWaitMs.Record(ctx, waitMs)\n\t\t}\n\t}\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to acquire connection: %w\", err)\n\t}\n\tdefer conn.Close()\n\n\tvar currentBranch string\n\tif err := conn.QueryRowContext(ctx, \"SELECT active_branch()\").Scan(&currentBranch); err != nil {\n\t\treturn fmt.Errorf(\"failed to read active branch: %w\", err)\n\t}\n\n\tregularTx, err := conn.BeginTx(ctx, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to begin regular tx: %w\", err)\n\t}\n\n\t// The journal counter and rows must commit in the SAME SQL transaction as\n\t// every mutation they describe. bd_events_journal and bd_events_seq are\n\t// dolt_ignored, so on the default split-transaction shape they would land in\n\t// the ignored transaction while the mutation lands in the regular one: a\n\t// mixed durable+wisp callback would then make the two transactions contend\n\t// with each other on the single bd_events_seq row, and the ignored commit\n\t// can fail AFTER the regular side has already committed — a mutation with no\n\t// journal record, which is exactly the state the same-transaction guarantee\n\t// exists to make impossible. In journal mode both planes therefore share the\n\t// pinned regular transaction. The default journal-off path keeps the\n\t// established split transactions untouched.\n\tjournalEnabled := s.eventsJournalEnabled.Load()\n\tignoredTx := regularTx\n\tif !journalEnabled {\n\t\t// NOTE (GH#3140 metrics skew): the pool-wait bracket above measures only\n\t\t// the FIRST acquisition (the regular conn). A borrow inside","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/transaction.go#L178-L214","documentation":"After reading the active branch, runDoltTransaction begins the regular SQL transaction with conn.BeginTx(ctx, nil). This error wraps a failure to start that transaction on the pinned connection — the session died between the branch read and BEGIN, the context was canceled, or the server rejected the transaction start (e.g. server shutting down, lock-table unavailable).","triggerScenarios":"ctx canceled/deadline exceeded exactly during BeginTx; connection dropped after `SELECT active_branch()` succeeded; Dolt server refusing new transactions (shutdown, storage error); server-side session killed.","commonSituations":"Flaky network to a remote Dolt server; graceful-shutdown windows where the server stops accepting transactions; embedded Dolt process exiting under memory pressure; very tight per-operation timeouts.","solutions":["Retry the operation — this is a pre-callback setup failure and withTransactionSetupRetry will retry it","Check Dolt server logs for shutdown/storage errors at the failure time","Widen the context deadline if it expired during BeginTx","Ensure only one process has the embedded Dolt database open if running in embedded mode"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// runInTransaction already retries pre-callback failures via withTransactionSetupRetry;\n// if you handle it manually:\nif err != nil && callbackNotStarted(err) {\n    return withTransactionSetupRetry(ctx, attempt)\n}","preventionTips":["Let the library's setup-retry wrapper handle retries instead of rolling your own","Keep network paths to the Dolt server stable (avoid aggressive NAT timeouts)","Avoid starting writes during known shutdown/maintenance windows","Give BeginTx-bearing operations sane (seconds, not milliseconds) deadlines"],"tags":["go","sql","transaction","dolt"],"backgroundTag":"begin-transaction-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}