Skip to content

RemotesAPI push: FastForward skips working set update, causing 'target has uncommitted changes' on next push #10807

@sussdorff

Description

@sussdorff

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

  1. Set up a Dolt SQL server with RemotesAPI enabled
  2. Push from a client — succeeds
  3. Check remote: SELECT * FROM dolt_diff_stat('HEAD', 'WORKING') — shows phantom row deletions
  4. Push again — fails with "target has uncommitted changes"
  5. CALL DOLT_CHECKOUT('.') and CALL DOLT_RESET('--hard') do NOT clear the stale state
  6. 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==""

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions