gitbutlerapp/gitbutler · error

'{other}' is not a conflicted uncommitted file; `but resolve

Error message

'{other}' is not a conflicted uncommitted file; `but resolve` takes either one commit or only conflicted files (see `but status`).

What it means

`but resolve` accepts either exactly one commit ID or a list of uncommitted file paths, and the path form requires every path to be currently conflicted — having non-unmerged index entries (stage != Unconflicted, see `conflicted_worktree_paths` in resolve.rs:113-122). If any supplied path is not in that conflicted set, the command bails naming the first offender.

Source

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

pub(crate) fn handle(
    ctx: &mut Context,
    out: &mut OutputChannel,
    cmd: Option<Subcommands>,
    targets: Vec<String>,
    ai: bool,
) -> Result<()> {
    // Conflicted uncommitted files are marked resolved; anything else is a commit.
    let conflicted_paths = if targets.is_empty() {
        Vec::new()
    } else {
        conflicted_worktree_paths(ctx)?
    };
    let commit_id = match targets.as_slice() {
        [] => None,
        [target] if !conflicted_paths.contains(target) => Some(target.clone()),
        _ => {
            if let Some(other) = targets.iter().find(|t| !conflicted_paths.contains(t)) {
                bail!(
                    "'{other}' is not a conflicted uncommitted file; `but resolve` takes either one commit or only conflicted files (see `but status`)."
                );
            }
            if ai {
                bail!(
                    "Conflicted uncommitted files can only be marked as resolved: `but resolve <path>...`"
                );
            }
            return mark_worktree_conflicts_resolved(ctx, out, targets);
        }
    };
    if ai {
        if cmd.is_some() {
            bail!(
                "--ai cannot be combined with a resolve subcommand. For one conflict, use `but resolve apply <path>[:<N>] --ai` instead."
            );
        }
        return resolve_with_ai(ctx, out, commit_id.as_deref());

View on GitHub (pinned to caf1f223d3)

Solutions

  1. List the currently conflicted files (`but resolve conflicts` or `git status`) and copy paths exactly.
  2. Re-check that the files still show as conflicted immediately before running resolve.
  3. If you meant a commit's conflicts, pass only that single commit ID — never mixed with paths.

Example fix

# before
but resolve src/lib.rs    # already resolved by the IDE -> not a conflicted uncommitted file

# after
but resolve conflicts     # list what is actually conflicted now
but resolve src/other.rs  # copy the exact path from that list
Defensive patterns

Strategy: validation

Validate before calling

# Only pass paths that are conflicted right now
but resolve conflicts | grep -F '<path>' || { echo 'not currently conflicted'; exit 2; }
but resolve '<path>'

Prevention

When it happens

Trigger: Passing a path that is no longer conflicted (resolved by an IDE or another tool in between), a typo'd or differently-quoted path (e.g. an added `./` prefix), or mixing a commit ID together with file paths in one invocation.

Common situations: Conflict state changing between checking status and running resolve; IDEs auto-resolving or reformatting files; Windows path-separator or quoting differences; stale copy-paste from an older conflict list.

Related errors


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