{"record":{"id":"573eb35a2042004e","repo":"gastownhall/beads","slug":"committing-migrations-w","errorCode":null,"errorMessage":"committing migrations: %w","messagePattern":"committing migrations: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/schema.go","lineNumber":739,"sourceCode":"\t}\n\tchangedDirtyTables, err := changedDirtyTableSignatures(ctx, db, dirtyBeforeSignatures)\n\tif err != nil {\n\t\treturn applied, fmt.Errorf(\"checking pre-existing dirty table diffs: %w\", err)\n\t}\n\tif len(changedDirtyTables) > 0 {\n\t\treturn applied, fmt.Errorf(\"pre-existing dirty tables changed during schema migration: %s\", strings.Join(changedDirtyTables, \", \"))\n\t}\n\n\tstaged, err := stageSchemaTables(ctx, db, dirtyBefore)\n\tif err != nil {\n\t\treturn applied, fmt.Errorf(\"staging migrations: %w\", err)\n\t}\n\tif !staged {\n\t\treturn applied, nil\n\t}\n\tif err := DrainCall(ctx, db, \"CALL DOLT_COMMIT('-m', 'schema: apply migrations')\"); err != nil {\n\t\tif !strings.Contains(strings.ToLower(err.Error()), \"nothing to commit\") {\n\t\t\treturn applied, fmt.Errorf(\"committing migrations: %w\", err)\n\t\t}\n\t}\n\n\treturn applied, nil\n}\n\nfunc migrationWorkNeeded(ctx context.Context, db DBConn) (bool, error) {\n\tif !mainSource.atLatest(ctx, db) || !ignoredSource.atLatest(ctx, db) {\n\t\treturn true, nil\n\t}\n\t// A database already at the latest numbered migration still needs work if it\n\t// predates the content_hash column (gastownhall/beads#4259 reporter fix No.2).\n\t// Without this, MigrateUp short-circuits before migrate() runs the idempotent\n\t// ALTER, so the recording/detection surface is never installed on exactly the\n\t// already-upgraded databases the fix is meant to protect.\n\thasMainHash, err := mainSource.hasContentHashColumn(ctx, db)\n\tif err != nil {\n\t\treturn false, err","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/schema.go#L721-L757","documentation":"This error wraps a failure from `CALL DOLT_COMMIT('-m', 'schema: apply migrations')` at the end of MigrateUp. After schema migrations have applied and staged changes were detected (stageSchemaTables returned true), the library attempts to commit the migration work so the database converges to a clean working set. If Dolt rejects the commit for any reason other than \"nothing to commit\" (which is tolerated and swallowed), the underlying driver error is wrapped as \"committing migrations: %w\".","triggerScenarios":"Calling MigrateUp (directly or via MigrateUpWithLock) when stageSchemaTables staged migration changes but the subsequent DOLT_COMMIT fails — e.g. Dolt server refused the commit, a merge/conflict state exists, the DB is read-only, or the connection dropped mid-commit. Only non-\"nothing to commit\" errors produce this.","commonSituations":"Running `bd` against an embedded Dolt database whose working set entered a conflicting state between staging and commit; opening a database on a read-only filesystem; an interrupted earlier migration pass leaving the repo in a state Dolt refuses to commit; Dolt version differences changing DOLT_COMMIT behavior; transient connection loss to the storage engine.","solutions":["Inspect the wrapped cause (%w) printed after \"committing migrations:\" — it names the actual Dolt failure; fix that condition first.","Run `bd doctor` (or `dolt status` in the .beads database dir) to check for a dirty/conflicting working set, then resolve or reset the conflicted tables.","Retry the open/migration after ensuring the database directory is writable and no other process holds the DB lock (MigrateUpWithLock takes the advisory lock for you).","If the working set is corrupted by a crashed pass, verify the migration self-heal path: re-run MigrateUp — the #4566 contract expects a retry from a clean working set to converge.","Check the installed Dolt/embedded-dolt version against the version beads was built for; upgrade or downgrade to a compatible release."],"exampleFix":"// before: opaque failure at open time\nif err := DrainCall(ctx, db, \"CALL DOLT_COMMIT('-m', 'schema: apply migrations')\"); err != nil {\n    return applied, fmt.Errorf(\"committing migrations: %w\", err)\n}\n// after: caller-side handling that inspects the cause and retries once\nvar openErr error\nfor i := 0; i < 2; i++ {\n    _, openErr = storage.Open(ctx, dbPath)\n    if openErr == nil || !strings.Contains(openErr.Error(), \"committing migrations\") {\n        break\n    }\n    time.Sleep(500 * time.Millisecond) // transient engine/lock condition\n}","handlingStrategy":"try-catch","validationCode":"// Go: ensure the database dir is writable and no merge state before migrating\nfunc canCommit(dbPath string) error {\n    fi, err := os.Stat(dbPath)\n    if err != nil || !fi.IsDir() {\n        return fmt.Errorf(\"db path missing: %s\", dbPath)\n    }\n    if err := unix.Access(dbPath, unix.W_OK); err != nil {\n        return fmt.Errorf(\"db not writable: %w\", err)\n    }\n    return nil\n}","typeGuard":"// Go: the wrapped error is opaque (%w of a driver error); narrow by message\nfunc isMigrationCommitError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"committing migrations:\")\n}","tryCatchPattern":"_, err := schema.MigrateUp(ctx, db)\nif err != nil {\n    var pathErr *os.PathError\n    switch {\n    case isMigrationCommitError(err):\n        // inspect wrapped cause, check `dolt status`, retry once\n    case errors.As(err, &pathErr):\n        // fix filesystem permission\n    default:\n        return err\n    }\n}","preventionTips":["Always migrate via MigrateUpWithLock so no competing process mutates the working set mid-commit","Keep the .beads database directory writable by the running user","Commit or clean user-staged changes before running migrations","Pin/verify the Dolt engine version beads was built against"],"tags":["database","dolt","migration","commit"],"backgroundTag":"migration-commit-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}