Bug Description
When pushing to a Dolt SQL server via RemotesAPI, every push succeeds but silently corrupts the remote's working set. The next push then fails with:
Error 1105 (HY000): target has uncommitted changes. --force required to overwrite
This makes reliable push/pull workflows impossible without --force on every push.
Root Cause
File: go/libraries/doltcore/env/actions/remotes.go, lines 88-100
case ref.FastForwardOnly:
onlyIgnored := false
roots, err := destDB.ResolveBranchRoots(ctx, destRef)
if err == nil {
onlyIgnored, _ = diff.WorkingSetContainsOnlyIgnoredTables(ctx, roots)
}
if onlyIgnored {
err = destDB.FastForward(ctx, destRef, commit) // BUG: no WS update
} else {
err = destDB.FastForwardWithWorkspaceCheck(ctx, destRef, commit)
}
When the remote's working set is clean (no staged/unstaged changes), WorkingSetContainsOnlyIgnoredTables returns true. This triggers FastForward instead of FastForwardWithWorkspaceCheck.
FastForward (doltdb.go:917-925) passes an empty workingSetPath to doFastForward:
_, err = ddb.db.FastForward(ctx, ds, hash, "") // empty workingSetPath!
doFastForward (database_common.go:407) skips the working set update when workingSetPath == "". Result: HEAD is updated but the working set still points to the old root hash.
FastForwardWithWorkspaceCheck (doltdb.go:891-915) correctly passes the working set path and updates both HEAD and the working set.
Reproduction
- Set up a Dolt SQL server with RemotesAPI enabled
- Push from a client — succeeds
- Check remote:
SELECT * FROM dolt_diff_stat('HEAD', 'WORKING') — shows phantom row deletions
- Push again — fails with "target has uncommitted changes"
CALL DOLT_CHECKOUT('.') and CALL DOLT_RESET('--hard') do NOT clear the stale state
- Server restart does NOT fix it (stale state is persisted in NBS manifest)
Environment: Dolt v1.85.0, both local and remote. Affects both embedded mode (remotesapi/HTTPS) and shared-server mode (SQL protocol push that goes through RemotesAPI on the remote).
Suggested Fix
Always use FastForwardWithWorkspaceCheck in the onlyIgnored branch — it handles clean working sets correctly and properly updates the working set alongside HEAD:
if onlyIgnored {
err = destDB.FastForwardWithWorkspaceCheck(ctx, destRef, commit) // was: FastForward
} else {
err = destDB.FastForwardWithWorkspaceCheck(ctx, destRef, commit)
}
Or simply remove the onlyIgnored optimization entirely, since FastForwardWithWorkspaceCheck handles both cases correctly.
Impact
This bug makes every second push fail for any client pushing to a Dolt SQL server. The only workaround is --force on every push (after pulling first to preserve others' changes). This affects all databases on the server, not just specific ones.
Key Files
| File |
Lines |
Description |
go/libraries/doltcore/env/actions/remotes.go |
88-100 |
Bug: onlyIgnored branch calls FastForward without WS update |
go/libraries/doltcore/doltdb/doltdb.go |
917-925 |
FastForward: passes empty workingSetPath |
go/libraries/doltcore/doltdb/doltdb.go |
891-915 |
FastForwardWithWorkspaceCheck: correctly passes WS path |
go/store/datas/database_common.go |
346-493 |
doFastForward: skips WS update when workingSetPath=="" |
Bug Description
When pushing to a Dolt SQL server via RemotesAPI, every push succeeds but silently corrupts the remote's working set. The next push then fails with:
This makes reliable push/pull workflows impossible without
--forceon every push.Root Cause
File:
go/libraries/doltcore/env/actions/remotes.go, lines 88-100When the remote's working set is clean (no staged/unstaged changes),
WorkingSetContainsOnlyIgnoredTablesreturnstrue. This triggersFastForwardinstead ofFastForwardWithWorkspaceCheck.FastForward(doltdb.go:917-925) passes an emptyworkingSetPathtodoFastForward:doFastForward(database_common.go:407) skips the working set update whenworkingSetPath == "". Result: HEAD is updated but the working set still points to the old root hash.FastForwardWithWorkspaceCheck(doltdb.go:891-915) correctly passes the working set path and updates both HEAD and the working set.Reproduction
SELECT * FROM dolt_diff_stat('HEAD', 'WORKING')— shows phantom row deletionsCALL DOLT_CHECKOUT('.')andCALL DOLT_RESET('--hard')do NOT clear the stale stateEnvironment: Dolt v1.85.0, both local and remote. Affects both embedded mode (remotesapi/HTTPS) and shared-server mode (SQL protocol push that goes through RemotesAPI on the remote).
Suggested Fix
Always use
FastForwardWithWorkspaceCheckin theonlyIgnoredbranch — it handles clean working sets correctly and properly updates the working set alongside HEAD:Or simply remove the
onlyIgnoredoptimization entirely, sinceFastForwardWithWorkspaceCheckhandles both cases correctly.Impact
This bug makes every second push fail for any client pushing to a Dolt SQL server. The only workaround is
--forceon every push (after pulling first to preserve others' changes). This affects all databases on the server, not just specific ones.Key Files
go/libraries/doltcore/env/actions/remotes.goonlyIgnoredbranch callsFastForwardwithout WS updatego/libraries/doltcore/doltdb/doltdb.goFastForward: passes emptyworkingSetPathgo/libraries/doltcore/doltdb/doltdb.goFastForwardWithWorkspaceCheck: correctly passes WS pathgo/store/datas/database_common.godoFastForward: skips WS update whenworkingSetPath==""