affaan-m/ECC · error

git rebase failed: {}{}

Error message

git rebase failed: {}{}

What it means

Thrown by rebase_onto_base at ecc2/src/worktree/mod.rs:950 when `git -C <worktree.path> rebase <base_branch>` exits non-zero. On failure the code first attempts `git -C <worktree.path> rebase --abort` to leave the worktree in a clean state, captures any abort warning, formats stdout+stderr from the failed rebase, and bails with both pieces. Unlike the merge path, this error always tries to clean up the in-progress rebase before propagating.

Source

Thrown at ecc2/src/worktree/mod.rs:950

            .arg("-C")
            .arg(&worktree.path)
            .args(["rebase", "--abort"])
            .output()
            .context("Failed to abort unsuccessful rebase")?;
        let abort_warning = if abort_output.status.success() {
            String::new()
        } else {
            format!(
                " (rebase abort warning: {})",
                String::from_utf8_lossy(&abort_output.stderr).trim()
            )
        };
        let stderr = format!(
            "{}\n{}",
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr)
        );
        anyhow::bail!("git rebase failed: {}{}", stderr.trim(), abort_warning);
    }

    let after_head = branch_head_oid_in_repo(&repo_root, &worktree.branch)?;
    let rebase_output = format!(
        "{}\n{}",
        String::from_utf8_lossy(&output.stdout),
        String::from_utf8_lossy(&output.stderr)
    );

    Ok(RebaseOutcome {
        branch: worktree.branch.clone(),
        base_branch: worktree.base_branch.clone(),
        already_up_to_date: before_head == after_head || rebase_output.contains("up to date"),
    })
}

pub fn branch_head_oid(worktree: &WorktreeInfo, branch: &str) -> Result<String> {
    let repo_root = base_checkout_path(worktree)?;

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Read the formatted stderr in the error message to find conflict paths; if the auto-abort succeeded the worktree is clean — resolve conflicts in a manual rebase (`git -C <worktree_path> rebase <base_branch>`), or pick a different strategy (merge instead).
  2. If the abort also failed (the trailing `(rebase abort warning: ...)` is non-empty), run `git -C <worktree_path> rebase --abort` manually until HEAD stabilizes, then investigate.
  3. Refresh the worktree's view of base_branch first: `git -C <worktree_path> fetch origin <base_branch>` so the rebase target is current.
  4. Fall back to merge_into_base if conflicts are too entangled to rebase cleanly.

Example fix

// before
let outcome = rebase_onto_base(&worktree)?;

// after: fall back to merge when rebase conflicts
let outcome = match rebase_onto_base(&worktree) {
    Ok(o) => o,
    Err(e) => {
        tracing::warn!("rebase failed, falling back to merge: {e}");
        // rebase_onto_base already aborted the in-progress rebase
        merge_into_base(&worktree).map(|m| RebaseOutcome {
            branch: m.branch,
            base_branch: m.base_branch,
            already_up_to_date: m.already_up_to_date,
        })?
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure base_branch is current and the worktree can see it
Command::new("git").arg("-C").arg(&worktree.path)
    .args(["fetch", "origin", &worktree.base_branch]).status()?;
if has_uncommitted_changes(&worktree)? {
    anyhow::bail!("worktree dirty; cannot safely rebase");
}

Type guard

null

Try / catch

match rebase_onto_base(&worktree) {
    Ok(o) => Ok(o),
    Err(e) if e.to_string().starts_with("git rebase failed") => {
        // rebase_onto_base already attempted --abort; fall back to a merge
        tracing::warn!("rebase failed, falling back to merge: {e}");
        merge_into_base(&worktree).map(|m| RebaseOutcome {
            branch: m.branch, base_branch: m.base_branch,
            already_up_to_date: m.already_up_to_date,
        })
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Content conflicts between the worktree branch and base_branch during replay; the base branch ref no longer exists or was force-pushed; a rebase hook (post-checkout, pre-rebase) rejected a step; binary/LFS conflicts; the worktree path is locked by another git process.

Common situations: Base branch advanced with conflicting changes since the worktree branched off; rebase of a long-lived feature branch with many squashed commits; pre-rebase hook (e.g. branch-protection) returns non-zero; LFS object missing on the base side.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/cfb2127db11b4bc5. Report an issue: GitHub.