gitbutlerapp/gitbutler · error

Commit {commit_ref} is not in a conflicted state. Only confl

Error message

Commit {commit_ref} is not in a conflicted state. Only conflicted commits can be resolved.

What it means

Thrown by `but resolve <commit>` when entering resolution (edit) mode for a commit that is not marked conflicted. After resolving the id via IdMap, the command loads the commit with repo.find_commit() and checks commit.is_conflicted(); only conflicted commits (e.g. produced by a GitButler rebase/update that hit conflicts) may enter resolution mode.

Source

Thrown at crates/but/src/command/legacy/resolve.rs:207

        }
        _ => bail!("'{commit_id_str}' does not refer to a commit"),
    }
}

fn enter_resolution(ctx: &mut Context, out: &mut OutputChannel, commit_id_str: &str) -> Result<()> {
    let t = theme::get();
    use gix::{prelude::ObjectIdExt as _, revision::walk::Sorting};

    let (commit_gix_oid, commit_ref) = parse_commit_id(ctx, commit_id_str)?;

    // Get the commit and check if it's conflicted
    let repo = ctx.repo.get()?;
    let commit = repo
        .find_commit(commit_gix_oid)
        .context("Failed to find commit")?;

    if !commit.is_conflicted() {
        bail!(
            "Commit {commit_ref} is not in a conflicted state. Only conflicted commits can be resolved."
        );
    }

    // Find which stack this commit belongs to
    let stacks = crate::legacy::workspace::applied_stacks(ctx)?;
    let mut found_stack_id = None;
    'outer: for stack in &stacks {
        // Check if this commit is in any of the stack's heads
        // TODO(ctx): use `ws` for that.
        // TODO(perf): This is likely to walk the whole graph.
        for head in &stack.branches {
            // Walk the commit history to see if our commit is in this stack
            let traversal = head
                .tip
                .attach(&repo)
                .ancestors()
                .sorting(Sorting::BreadthFirst)

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Run `but resolve conflicts` (or `but status`) to list the commits that are actually conflicted right now and copy the current id
  2. If the commit was conflicted earlier but is fine now, nothing to do — conflicts were already resolved
  3. If you expected conflicts, run `but update`/the operation that produces conflicts again and re-list

Example fix

// before
but resolve 4a9c1f2
// error: Commit 4a9c1f2 is not in a conflicted state...

// after
but resolve conflicts   # list current conflicted commits
but resolve <id-from-list>
Defensive patterns

Strategy: validation

Validate before calling

# list commits that are actually conflicted before targeting one
but resolve conflicts > /tmp/conflicts.txt
grep -q . /tmp/conflicts.txt || { echo 'nothing conflicted'; exit 0; }
# then pass an id from that listing to `but resolve <id>`

Prevention

When it happens

Trigger: Running `but resolve <commit-id>` (or a subcommand that starts edit mode) where the target commit is a normal commit, or a commit whose conflicts were already resolved by a previous run/rebase, so is_conflicted() returns false.

Common situations: Pointing at a commit oid from an older workspace state after conflicts were already fixed; passing a branch-tip or regular commit instead of the conflicted commit; re-running an old command from shell history after the workspace moved on.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/244f4feebc1445ce. Report an issue: GitHub.