gitbutlerapp/gitbutler · error · anyhow::Error

Unexpected hunk with neither newlines or oldlines being 0

Error message

Unexpected hunk with neither newlines or oldlines being 0

What it means

When GitButler computes which hunks to commit, the primary algorithm must produce hunks in order; if not, it retries with `to_additive_hunks_fallback`, which only understands purely additive (old_lines == 0) or purely subtractive (new_lines == 0) hunks. A selected hunk with both counts non-zero (a modification) reaching this fallback trips the bail — the fallback was never designed for replacement hunks.

Source

Thrown at crates/but-core/src/tree/mod.rs:471

                     new_start,
                     new_lines,
                 }| {
                    if old_lines == 0 {
                        Ok(HunkHeader {
                            old_start: 0,
                            old_lines: 0,
                            new_start,
                            new_lines,
                        })
                    } else if new_lines == 0 {
                        Ok(HunkHeader {
                            old_start,
                            old_lines,
                            new_start: 0,
                            new_lines: 0,
                        })
                    } else {
                        bail!("Unexpected hunk with neither newlines or oldlines being 0");
                    }
                },
            )
            .collect::<Result<_, _>>()?;
        let (hunks_to_commit, rejected) =
            to_additive_hunks_fallback(hunks, worktree_hunks, worktree_hunks_no_context);
        if !in_order(&hunks_to_commit) {
            bail!(
                "Alternative hunks algorithms still didn't produce properly ordered hunks or saw duplicate inputs: {hunks_to_commit:?}"
            );
        }
        (hunks_to_commit, rejected)
    } else {
        (hunks_to_commit, rejected)
    };
    Ok(res)
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Commit the whole file instead of individual hunks for the affected file.
  2. Change the hunk selection (e.g. include the full modification hunk rather than splitting around it) and retry.
  3. Update GitButler — hunk-selection algorithms are actively improved and this is a known class of fallback limitation.
  4. Capture the hunk headers (logged at info level before the fallback runs) and file a bug report.
Defensive patterns

Strategy: fallback

Type guard

// Rust — a selected hunk the fallback algorithm can handle must be purely additive or purely subtractive
fn is_pure_hunk(h: &but_diff::HunkHeader) -> bool {
    h.old_lines == 0 || h.new_lines == 0
}

Try / catch

// Fall back to committing the whole file when hunk-level commit fails
match commit_selected_hunks(path, hunks) {
    Ok(()) => Ok(()),
    Err(err) if err.to_string().contains("Unexpected hunk") => {
        tracing::warn!("hunk fallback failed for {path}; committing whole file");
        commit_whole_file(path)
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: Partially staging hunks such that the primary algorithm emits out-of-order/duplicate hunks and the retry set contains a modification hunk — typically hand-picked hunk selections on files with interleaved adds, deletes and edits.

Common situations: Selecting individual modified hunks in the GitButler UI on files with mixed changes; hunk selections produced after external tools (formatters, editors) race the diff computation.

Related errors


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