{"record":{"id":"8a6a3360b036e3e3","repo":"gastownhall/beads","slug":"dolt-commit-w-8a6a33","errorCode":null,"errorMessage":"dolt commit: %w","messagePattern":"dolt commit: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/embeddeddolt/version_control.go","lineNumber":140,"sourceCode":"// CommitAll commits the entire working set (config included) with the given\n// message and reports whether a commit actually landed — the\n// storage.VersionControl entry point for the explicit operator commands\n// (bd vc commit, bd dolt commit). Embedded commits already stage everything\n// via DOLT_COMMIT('-Am'); what the explicit commands need from this store is\n// the committed bool, which replaces their HEAD-before/HEAD-after comparison\n// (racy against concurrent writers, and two extra engine opens per call —\n// the same reasoning as CommitPending's doc comment).\nfunc (s *EmbeddedDoltStore) CommitAll(ctx context.Context, message string) (bool, error) {\n\treturn s.commitAll(ctx, message, true)\n}\n\nfunc commitAllInTx(ctx context.Context, tx *sql.Tx, message string, tolerateEmpty bool) (bool, error) {\n\tif _, err := tx.ExecContext(ctx, \"CALL DOLT_COMMIT('-Am', ?)\", message); err != nil {\n\t\tif issueops.IsNothingToCommitError(err) {\n\t\t\tif tolerateEmpty {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, fmt.Errorf(\"dolt commit: %w\", err)\n\t\t}\n\t\treturn false, wrapCommitIndeterminate(\"dolt commit\", err)\n\t}\n\treturn true, nil\n}\n\n// stageAndCommitAfterSQLCommit preserves the no-replay boundary for version\n// publication after an already-visible SQL mutation.\nfunc stageAndCommitAfterSQLCommit(ctx context.Context, db versioncontrolops.DBConn, dirtyTables map[string]bool, commitMsg, author string) error {\n\tif err := versioncontrolops.StageAndCommit(ctx, db, dirtyTables, commitMsg, author); err != nil {\n\t\treturn wrapCommitIndeterminate(\"embeddeddolt: stage and commit after SQL commit\", err)\n\t}\n\treturn nil\n}\n\n// Commit stages and commits the full working set. A clean working set is not\n// an error here: the server store (DoltStore.Commit et al., via\n// isDoltNothingToCommit) has always tolerated Dolt's \"nothing to commit\"","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/version_control.go#L122-L158","documentation":"commitAllInTx ran `CALL DOLT_COMMIT('-Am', ?)` and Dolt reported there is nothing to commit (the working set matches HEAD). Because tolerateEmpty was false, the caller explicitly wanted an error for empty commits, so the NothingToCommit error is wrapped and returned as `dolt commit: %w`. When the error is NOT nothing-to-commit, it is instead routed to wrapCommitIndeterminate — this specific error means a clean, known-empty commit.","triggerScenarios":"Calling commitAllInTx (directly or via CommitPending / runTransactionWithMessage paths) with tolerateEmpty=false on a database whose working set has no changes — e.g. committing pending changes when none exist, or double-committing after a prior successful commit.","commonSituations":"Running a pull/merge flow that pre-commits pending changes when everything is already committed; calling commit twice in one command; tests asserting that empty commits surface as errors rather than no-ops.","solutions":["This is usually benign: check the wrapped error for the nothing-to-commit signature (issueops.IsNothingToCommitError) and treat it as a no-op.","Pass tolerateEmpty=true when an empty working set is acceptable, so commitAllInTx returns (false, nil) instead of erroring.","Remove redundant commit calls — verify pending changes exist (dirty tracker / dolt status equivalent) before committing.","If you expected changes to exist, inspect why the working set is empty: the earlier commit may have already succeeded (possibly indeterminately — check for storage.ErrCommitIndeterminate upstream)."],"exampleFix":"// before: erroring on empty commit\ncommitted, err := commitAllInTx(ctx, tx, msg, false)\n\n// after: tolerate empty when it is expected\ncommitted, err := commitAllInTx(ctx, tx, msg, true)\nif err == nil && !committed {\n    // nothing to commit — fine\n}","handlingStrategy":"validation","validationCode":"// check for pending changes before requesting a strict commit\n// (e.g. via a status/dirty API)\nif !store.HasPendingChanges(ctx) {\n    return nil // nothing to commit; skip the strict commit\n}","typeGuard":null,"tryCatchPattern":"if err := commitStrict(ctx); err != nil {\n    if isNothingToCommit(err) { // issueops.IsNothingToCommitError signature\n        return nil // benign: working set already clean\n    }\n    return err\n}","preventionTips":["Pass tolerateEmpty=true whenever an empty working set is acceptable.","Check dirty/pending state before forcing a commit.","Avoid double-committing within one command flow.","Remember an empty commit often means an earlier commit already succeeded — verify before treating it as a failure."],"tags":["embeddeddolt","dolt-commit","empty-commit","version-control"],"backgroundTag":"nothing-to-commit","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}