affaan-m/ECC · warning
cannot reset a staged hunk while the file also has unstaged…
Error message
cannot reset a staged hunk while the file also has unstaged changes; unstage it first
What it means
reset_hunk refuses to reverse-apply a staged hunk (`git apply -R --index`) when the same file still has unstaged changes. Doing so would corrupt the working tree state because git's index-level reverse apply requires the working tree to match the index for that file. The library enforces the ordering: unstage or discard unstaged hunks first.
Solutions
- Unstage the file first (unstage_path or unstage_hunk), then reset the desired hunks.
- Discard the unstaged hunks of that file first (reset_hunk on its Unstaged hunks), then reset the staged hunk.
- In UI code, guard: only enable staged-hunk reset when entry.unstaged is false.
Example fix
// before: direct reset of staged hunk
reset_hunk(&worktree, &entry, &staged_hunk)?;
// after: unstage first when mixed state
if entry.unstaged {
unstage_path(&worktree, &entry)?;
}
reset_hunk(&worktree, &entry, &staged_hunk)?; Defensive patterns
Strategy: validation
Validate before calling
fn can_reset_staged_hunk(entry: &GitStatusEntry) -> bool {
!entry.unstaged
} Type guard
fn staged_hunk_reset_ok(entry: &GitStatusEntry, hunk: &GitPatchHunk) -> bool {
matches!(hunk.section, GitPatchSectionKind::Staged) && !entry.unstaged
} Try / catch
match reset_hunk(&worktree, &entry, &hunk) {
Err(e) if e.to_string().contains("unstaged changes") => {
unstage_path(&worktree, &entry)?;
reset_hunk(&worktree, &entry, &hunk)?;
}
other => other?,
} Prevention
- Before resetting a staged hunk, check whether the file also has unstaged hunks.
- Enforce order in UI flows: resolve unstaged hunks first, then staged ones.
- Disable staged-hunk reset buttons when the status entry shows mixed staged/unstaged state.
When it happens
Trigger: Calling reset_hunk with a hunk whose section is Staged while entry.unstaged == true — i.e. the file appears in both the staged and unstaged sections of the status view.
Common situations: Editing a file after partially staging it (via stage_hunk or `git add -p`), then trying to reset the staged portion directly; UIs that do not disable staged-hunk reset actions when the file has additional unstaged edits.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Base branch is not checked out in repo root (currently )
- no staged changes to commit
- Repository root has uncommitted changes; commit or stash…
- selected hunk is already staged
- selected hunk is not staged
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/85c757bdda8a9ffb.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/worktree/mod.rs:441
)
}
pub fn reset_hunk(
worktree: &WorktreeInfo,
entry: &GitStatusEntry,
hunk: &GitPatchHunk,
) -> Result<()> {
if entry.untracked {
anyhow::bail!("cannot reset hunks for untracked files");
}
match hunk.section {
GitPatchSectionKind::Unstaged => {
git_apply_patch(&worktree.path, &["-R"], &hunk.patch, "reset selected hunk")
}
GitPatchSectionKind::Staged => {
if entry.unstaged {
anyhow::bail!(
"cannot reset a staged hunk while the file also has unstaged changes; unstage it first"
);
}
git_apply_patch(
&worktree.path,
&["-R", "--index"],
&hunk.patch,
"reset selected staged hunk",
)
}
}
}
pub fn commit_staged(worktree: &WorktreeInfo, message: &str) -> Result<String> {
let message = message.trim();
if message.is_empty() {
anyhow::bail!("commit message cannot be empty");
}View on GitHub (pinned to 8321021c54)