affaan-m/ECC · warning

selected hunk is not staged

Error message

selected hunk is not staged

What it means

unstage_hunk unstages a hunk by reverse-applying its patch to the index (`git apply -R --cached`) and therefore requires the hunk to come from the staged section. If the hunk's section is Unstaged, the library throws this precondition error because an unstaged hunk cannot be removed from the index.

Solutions

  1. Verify hunk.section == GitPatchSectionKind::Staged before calling unstage_hunk.
  2. Re-fetch the patch view after every stage/unstage/reset operation so hunk sections reflect current index state.
  3. Route unstaged hunks to stage_hunk (or discard via reset_hunk) instead.

Example fix

// before
unstage_hunk(&worktree, &hunk)?;

// after
if hunk.section == GitPatchSectionKind::Staged {
    unstage_hunk(&worktree, &hunk)?;
}
Defensive patterns

Strategy: type-guard

Validate before calling

if hunk.section != GitPatchSectionKind::Staged {
    return Err(anyhow!("hunk is not staged; nothing to unstage"));
}

Type guard

fn is_unstageable(hunk: &GitPatchHunk) -> bool {
    matches!(hunk.section, GitPatchSectionKind::Staged)
}

Try / catch

match unstage_hunk(&worktree, &hunk) {
    Ok(()) => refresh_patch_view(),
    Err(e) if e.to_string().contains("not staged") => refresh_patch_view(),
    Err(e) => eprintln!("unstage hunk failed: {e:#}"),
}

Prevention

When it happens

Trigger: Calling unstage_hunk(worktree, hunk) with hunk.section == GitPatchSectionKind::Unstaged, typically from UI code that wires both staged and unstaged diff panels to a single 'unstage' handler.

Common situations: Reusing one context menu for both diff sections; stale hunk objects captured before a previous staging operation moved the hunk between sections.

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


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/6d76c81d26dc0ffd. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/worktree/mod.rs:416

        }))
    }
}

pub fn stage_hunk(worktree: &WorktreeInfo, hunk: &GitPatchHunk) -> Result<()> {
    if hunk.section != GitPatchSectionKind::Unstaged {
        anyhow::bail!("selected hunk is already staged");
    }
    git_apply_patch(
        &worktree.path,
        &["--cached"],
        &hunk.patch,
        "stage selected hunk",
    )
}

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");
    }

View on GitHub (pinned to 8321021c54)