xai-org/grok-build · error

merge into '{target_branch}' succeeded but push failed ({sta

Error message

merge into '{target_branch}' succeeded but push failed ({status:?}): {}

What it means

After a successful merge into the target branch, the flow optionally pushes to origin. If the push step exits with a non-Ok classification (network/auth/rejected non-fast-forward etc.), the library raises this error noting the merge itself succeeded but the push failed, with scrubbed push output for diagnostics.

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:3330

    }
    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:?}): {}",
        scrub_git_output(&out)
    );
    Ok(())
}
/// `Push` (`workspace.git_push`): push a branch (or current `HEAD`) to `origin`,
/// classifying the outcome. Never forces. Output is credential-scrubbed.
pub async fn push_branch(git_root: &Path, branch: Option<&str>) -> Result<GitPushResult> {
    let refspec = branch.unwrap_or("HEAD");
    if let Some(branch) = branch {
        ensure_ref_arg_safe(branch, "branch")?;
    }
    let (ok, out) = git_cli_raw_mut(
        git_root,
        &["push", "-u", "origin", "--end-of-options", refspec],
    )
    .await?;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Fetch and inspect the remote: if it diverged, rebase/merge onto the updated target branch locally, then push again.
  2. Fix credentials (git credential helper, refreshed token, SSH key) and verify `git push` manually.
  3. If the local tree already holds the merge, a simple retry after resolving the remote state is safe — the merge itself succeeded.
  4. Check remote branch-protection rules or use a PR-based flow if direct pushes to the target branch are blocked.

Example fix

// before
git_ops.merge_to_main(&root, "session/abc", "main", true).await?; // fails when origin moved
// after
match git_ops.merge_to_main(&root, "session/abc", "main", true).await {
    Ok(_) => {},
    Err(e) if e.to_string().contains("push failed") => {
        // merge committed locally; reconcile with origin then re-push
        run_git(&root, &["pull", "--rebase"])?;
        run_git(&root, &["push"])?;
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight: check remote connectivity and auth
Command::new("git").args(["ls-remote", "origin", "-h", "refs/heads/main"]).status()?;

Try / catch

// push failures after a successful merge are often transient or need rebase
if let Err(e) = op().await {
    if e.to_string().contains("push failed") {
        reconcile_with_origin()?; // fetch + rebase/merge onto updated target
        retry_once(op).await?;
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Running merge-to-target with push=true (crates/codegen/xai-grok-workspace/src/session/git.rs:3330) when `git push` fails: remote rejected the update (diverged/non-fast-forward), missing or expired credentials, no write permission, offline, or push protected-branch rules.

Common situations: Origin moved ahead while the session ran (someone else pushed to main); CI machine has no git credentials or an expired token; branch protection on the remote blocks direct pushes; corporate proxy/firewall blocks the remote.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/83617f8a6dcb6805. Report an issue: GitHub.