xai-org/grok-build · error · anyhow::Error
merge of ' ' into ' ' failed
Error message
merge of '{conv_branch}' into '{target_branch}' failed: {} What it means
In the merge-to-main flow, when `git merge` of the session branch into the target branch fails without producing a structured Conflicts outcome, the code checks out the session branch for safety and bails with the scrubbed merge output. This covers hard merge failures rather than cleanly detected conflicts.
Solutions
- Read the scrubbed merge_out in the message and fix the underlying git error
- Clean or commit untracked files that would be overwritten by the merge (`git clean -fd` / commit)
- Verify both branches exist locally: `git rev-parse --verify <branch>`
- Abort any partial merge (`git merge --abort`) and retry
Example fix
// before merge_to_main(git_root, conv_branch, "main").await?; // after git status --porcelain # clean worktree first git merge --abort 2>/dev/null || true merge_to_main(git_root, conv_branch, "main").await?;
Defensive patterns
Strategy: try-catch
Validate before calling
for b in [conv_branch, target_branch] {
let ok = std::process::Command::new("git").arg("-C").arg(git_root).args(["rev-parse","--verify",b]).output()?;
if !ok.status.success() { anyhow::bail!("branch {b} missing"); }
}
if !git_root.join(".git/index.lock").exists() { /* ok */ } else { anyhow::bail!("index.lock present"); } Type guard
fn merge_failed_not_conflicts(msg: &str) -> bool { msg.contains("into '") && msg.contains("failed") } Try / catch
match merge_to_main(git_root, conv_branch, target).await {
Ok(r) => match r.outcome { Conflicts{files} => resolve(files), _ => ok() },
Err(e) if e.to_string().contains("merge of '") => {
let _ = git_cli(git_root, &["merge","--abort"]).await;
Err(e.context("clean worktree / verify branches, then retry"))
}
Err(e) => Err(e),
} Prevention
- Keep the worktree clean before initiating merges
- Ensure both branches exist locally (fetch first)
- Never run concurrent git operations in the same worktree
- Clear stale index.lock after abnormal terminations
When it happens
Trigger: Merging conv_branch into target_branch exits non-zero without the conflict-detection path triggering — e.g. merge aborted due to dirty state, refs not found, or git refusing the merge.
Common situations: Untracked files in target branch that the merge would overwrite; missing/renamed session branch; index.lock contention; unrelated histories.
Related errors
- merge of base ref ' ' failed
- git command failed
- git fetch --no-tags origin
- git status failed
- git worktree add failed
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/5c636b1e3721b4f3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:3314
});
}
let in_progress = git_cli_raw(git_root, &["rev-parse", "-q", "--verify", "MERGE_HEAD"])
.await?
.0;
if in_progress {
let files = git_cli(git_root, &["diff", "--name-only", "--diff-filter=U"])
.await?
.lines()
.map(str::to_owned)
.collect();
let _ = git_cli_raw(git_root, &["merge", "--abort"]).await;
checkout_branch(git_root, conv_branch, false).await?;
return Ok(GitMergeToMainResult {
outcome: GitMergeToMainOutcome::Conflicts { files },
});
}
let _ = checkout_branch(git_root, conv_branch, false).await;
anyhow::bail!(
"merge of '{conv_branch}' into '{target_branch}' failed: {}",
scrub_git_output(&merge_out)
)
}
/// Push the merged target to origin when `push` is set, failing loudly (never
/// forcing) so publish never records a deploy against an unpushed target.
async fn push_merged_target_if_requested(
git_root: &Path,
target_branch: &str,
push: bool,
) -> Result<()> {
if !push {
return Ok(());
}
let (status, out) = push_classified(git_root).await?;
anyhow::ensure!(
status == PushStatus::Ok,
"merge into '{target_branch}' succeeded but push failed ({status:?}): {}",View on GitHub (pinned to bc7f02eddd)