affaan-m/ECC · warning · anyhow::Error
cannot reset hunks for untracked files
Error message
cannot reset hunks for untracked files
What it means
reset_hunk refuses to operate when `entry.untracked == true`. Untracked files have no tracked baseline in HEAD, so the reverse-patch logic reset_hunk uses (`git apply -R` / `-R --index`) is meaningless for them. reset_path already handles untracked entries by deleting them from the filesystem; reset_hunk is the wrong entry point.
Source
Thrown at ecc2/src/worktree/mod.rs:432
pub fn unstage_hunk(worktree: &WorktreeInfo, hunk: &GitPatchHunk) -> Result<()> {
if hunk.section != GitPatchSectionKind::Staged {
anyhow::bail!("selected hunk is not staged");
}
git_apply_patch(
&worktree.path,
&["-R", "--cached"],
&hunk.patch,
"unstage selected hunk",
)
}
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",
)View on GitHub (pinned to 01e15490f0)
Solutions
- Branch on `entry.untracked`: route untracked entries to reset_path (which deletes them) instead of reset_hunk.
- For untracked entries, `git_status_patch_view` already returns None — derive hunks only from that view so untracked hunks never reach reset_hunk.
- Hide the per-hunk reset control on untracked rows.
Example fix
// before
reset_hunk(&worktree, &entry, &hunk)?;
// after
if entry.untracked {
reset_path(&worktree, &entry)?; // deletes the untracked file
} else {
reset_hunk(&worktree, &entry, &hunk)?;
} Defensive patterns
Strategy: type-guard
Validate before calling
use crate::worktree::{GitStatusEntry, reset_hunk, reset_path};
fn reset_entry_or_hunk(
worktree: &WorktreeInfo,
entry: &GitStatusEntry,
hunk: Option<&GitPatchHunk>,
) -> anyhow::Result<()> {
if entry.untracked {
return reset_path(worktree, entry); // deletes the file
}
match hunk {
Some(h) => reset_hunk(worktree, entry, h),
None => reset_path(worktree, entry),
}
} Type guard
fn is_tracked(entry: &GitStatusEntry) -> bool {
!entry.untracked
} Try / catch
match reset_hunk(&worktree, &entry, &hunk) {
Ok(()) => { /* refresh */ }
Err(e) if format!("{e}").contains("untracked files") => {
reset_path(&worktree, &entry)?;
}
Err(e) => return Err(e),
} Prevention
- Route untracked rows to reset_path; never construct hunks for them.
- Hide per-hunk reset UI on untracked entries.
- Derive hunks only from `git_status_patch_view`, which already returns None for untracked paths.
When it happens
Trigger: Caller selected a hunk belonging to an untracked file (where `git_status_patch_view` returns `None`, but a stale hunk was constructed elsewhere) and passed it with the entry to reset_hunk. UI offered a per-hunk reset on an untracked row.
Common situations: Stale GitStatusEntry retained after the file transitioned to untracked; UI dispatch table does not distinguish untracked rows from tracked ones for the reset verb.
Related errors
- selected hunk is already staged
- selected hunk is not staged
- cannot reset a staged hunk while the file also has unstaged
- commit message cannot be empty
- no staged changes to commit
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/7357b323b26afff1.
Report an issue: GitHub.