{"record":{"id":"8b1bbbedd28bd3cb","repo":"gastownhall/beads","slug":"s-w-w-8b1bbb","errorCode":null,"errorMessage":"%s: %w: %w","messagePattern":"(.+?): %w: %w","errorType":"exception","errorClass":"storage.ErrCommitIndeterminate","httpStatus":null,"severity":"critical","filePath":"internal/storage/embeddeddolt/transaction.go","lineNumber":66,"sourceCode":"\t\tcommitMsg, err = fn(&embeddedTransaction{tx: tx, dirty: &tracker})\n\t\treturn err\n\t}); err != nil {\n\t\treturn err\n\t}\n\n\t// Create a Dolt version commit from the working set changes.\n\tif commitMsg != \"\" && len(tracker.DirtyTables()) > 0 {\n\t\tif err := s.withMutatingDBConn(ctx, func(db versioncontrolops.DBConn) error {\n\t\t\treturn versioncontrolops.StageAndCommit(ctx, db, tracker.DirtyTables(), commitMsg, commitAuthor)\n\t\t}); err != nil {\n\t\t\treturn wrapCommitIndeterminate(\"embeddeddolt: stage and commit after SQL commit\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc wrapCommitIndeterminate(op string, err error) error {\n\treturn fmt.Errorf(\"%s: %w: %w\", op, err, storage.ErrCommitIndeterminate)\n}\n\ntype embeddedTransaction struct {\n\ttx    *sql.Tx\n\tdirty *versioncontrolops.DirtyTableTracker\n}\n\nfunc (t *embeddedTransaction) CreateIssue(ctx context.Context, issue *types.Issue, actor string) error {\n\tbc, err := issueops.NewBatchContext(ctx, t.tx, storage.BatchCreateOptions{SkipPrefixValidation: true})\n\tif err != nil {\n\t\treturn err\n\t}\n\tresult, err := issueops.CreateIssueInTxWithResult(ctx, t.tx, bc, issue, actor)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor table := range issueops.CreateIssueDirtyTables(ctx, issue, result) {\n\t\tt.dirty.MarkDirty(table)","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/transaction.go#L48-L84","documentation":"wrapCommitIndeterminate marks a Dolt transaction commit whose outcome could not be determined: the commit call failed, but the library cannot tell whether the data actually landed. The returned error chains the operation name, the underlying driver error, and storage.ErrCommitIndeterminate so callers can detect the ambiguous-outcome family with errors.Is. It is raised from commitEmbeddedTx and the commitAllInTx / runTransactionWithMessage / stageAndCommitAfterSQLCommit paths whenever a DOLT_COMMIT (or transaction flush) fails in a way that is not a clean, provable rollback.","triggerScenarios":"A transaction commit inside the embedded store fails with a non-nothing-to-commit error from Dolt (driver/connection failure, crash mid-commit, Dolt internal error) during commitEmbeddedTx, commitAllInTx, stageAndCommitAfterSQLCommit, commitAllInTx via runTransactionWithMessage, or joinTransactionCleanupError aggregation.","commonSituations":"Process crash or kill during a `bd` write so the transaction outcome on disk is unknown; Dolt storage-layer errors mid-commit; a test (TestDoltCommitResponseLossIsIndeterminate) simulating response loss; concurrent access corrupting transaction state so the commit result is ambiguous.","solutions":["Treat the operation as ambiguous: check the current state (read back the rows / HEAD) before retrying instead of blindly re-applying the write.","Use errors.Is(err, storage.ErrCommitIndeterminate) to branch on this family specifically, then re-run the intended operation idempotently or reconcile.","Inspect the wrapped driver error (%w in the middle) for the root cause — connection, disk, or Dolt internal — and fix that first.","Run `bd doctor` / integrity checks on the embedded database if you suspect a partially applied commit, then retry the command.","If caused by crashes, ensure only one bd process writes at a time and retry the failed command after verifying state."],"exampleFix":"// before: retrying blindly after any commit error\nif err := tx.Commit(); err != nil {\n    return retry(op)\n}\n\n// after: detect the indeterminate family first\nif err := doWrite(ctx); err != nil {\n    if errors.Is(err, storage.ErrCommitIndeterminate) {\n        if exists(op.Key()) {\n            return nil // already applied\n        }\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isCommitIndeterminate(err error) bool {\n    return errors.Is(err, storage.ErrCommitIndeterminate)\n}","tryCatchPattern":"if err := doWrite(ctx); err != nil {\n    if errors.Is(err, storage.ErrCommitIndeterminate) {\n        // outcome unknown: read back state / HEAD before any retry,\n        // make the operation idempotent, do not blindly re-apply\n        if alreadyApplied(op.Key()) {\n            return nil\n        }\n    }\n    return err\n}","preventionTips":["Keep write operations idempotent so a re-run after an unknown outcome is safe.","Run a single bd writer per database; avoid concurrent processes on the same embedded store.","Check state (HEAD/rows) after any crash before re-running write commands.","Handle ErrCommitIndeterminate explicitly rather than lumping it with ordinary errors.","Use `bd doctor` after crashes to reconcile possibly-partial commits."],"tags":["embeddeddolt","transaction","commit","indeterminate-outcome"],"backgroundTag":"commit-indeterminate","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}