gastownhall/beads · error

fast-forward to %s: %w

Error message

fast-forward to %s: %w

What it means

FastForwardAdopt executes CALL DOLT_MERGE('--ff-only', ?) after validating the ref. If the merge fails — the ref doesn't exist locally, the merge would not be a pure fast-forward, uncommitted changes block the merge, or a Dolt error occurs — the error is wrapped as "fast-forward to <ref>: %w".

Source

Thrown at internal/storage/versioncontrolops/fastforward.go:95

	}
	if err := rows.Err(); err != nil {
		return false, fmt.Errorf("iterate dolt_status: %w", err)
	}

	return clean, nil
}

// FastForwardAdopt fast-forwards the current branch to ref via
// CALL DOLT_MERGE('--ff-only', ref). ref must already be cached locally
// (e.g. a remote-tracking ref updated by a prior fetch); this performs no
// fetch of its own and fails if the merge would not be a pure fast-forward.
func FastForwardAdopt(ctx context.Context, db DBConn, ref string) error {
	if err := issueops.ValidateRef(ref); err != nil {
		return fmt.Errorf("invalid ref: %w", err)
	}

	if _, err := db.ExecContext(ctx, "CALL DOLT_MERGE('--ff-only', ?)", ref); err != nil {
		return fmt.Errorf("fast-forward to %s: %w", ref, err)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fetch first (CALL DOLT_FETCH('origin')) — FastForwardAdopt performs no fetch of its own.
  2. Check WorkingSetClean and commit or stash uncommitted changes before the merge.
  3. If the branch has diverged, decide whether to rebase locally or use a non-ff strategy; --ff-only will not overwrite local commits.
  4. Read the wrapped Dolt error message — it names the merge conflict or unknown-ref cause.

Example fix

// before
versioncontrolops.FastForwardAdopt(ctx, db, "origin/main")
// after
if err := fetchOrigin(ctx, db); err != nil { return err } // ensure ref is cached
clean, err := versioncontrolops.WorkingSetClean(ctx, db)
if err != nil || !clean { return fmt.Errorf("working set dirty, aborting ff") }
versioncontrolops.FastForwardAdopt(ctx, db, "origin/main")
Defensive patterns

Strategy: validation

Validate before calling

// fetch + preconditions before FastForwardAdopt
if err := fetchOrigin(ctx, db); err != nil { return err } // CALL DOLT_FETCH('origin')
clean, err := versioncontrolops.WorkingSetClean(ctx, db)
if err != nil { return err }
if !clean { return fmt.Errorf("uncommitted changes block --ff-only merge") }

Try / catch

err := versioncontrolops.FastForwardAdopt(ctx, db, "origin/main")
if err != nil {
    if strings.Contains(err.Error(), "not a fast-forward") || strings.Contains(err.Error(), "diverged") {
        return fmt.Errorf("branch diverged; rebase or merge manually")
    }
    return err
}

Prevention

When it happens

Trigger: Calling FastForwardAdopt with a valid-syntax ref that was never fetched (unknown ref); local branch has commits not on ref (non-fast-forward); dirty working set; detached or unexpected current branch; concurrent Dolt session state conflict.

Common situations: Skipping the fetch step the docs require; local work diverged from origin/main so --ff-only refuses; uncommitted dolt_status entries; running against a branch whose upstream was force-pushed and rewrote history.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/85aea4d8c0c7fa77. Report an issue: GitHub.