gitbutlerapp/gitbutler · error
Type-changed items can't be discard by hunks - use the…
Error message
Type-changed items can't be discard by hunks - use the whole-file mode instead
What it means
Thrown by discard_workspace_changes when a modification/rename change is flagged as a typechange (e.g. file became a symlink or executable transition) and the caller attempts hunk-level discard. Hunk diffs are not meaningful across type changes, so only whole-file mode is allowed. Note the message contains a typo ('can't be discard') but is unconditional for any is_typechange() flag.
Solutions
- Discard the entire change for typechanged paths rather than selected hunks.
- Check change flags for is_typechange() before entering the hunk path and split such changes into a whole-file discard queue.
- If only the mode bit changed, restore the whole entry to its previous state with whole-file mode.
Example fix
// before
hunk::restore_state_to_worktree(wt_change, previous_state, hunks)?;
// after
if wt_change.flags.is_some_and(|f| f.is_typechange()) {
whole_file_restore(wt_change, previous_state)?;
} else {
hunk::restore_state_to_worktree(wt_change, previous_state, hunks)?;
} Defensive patterns
Strategy: validation
Validate before calling
fn is_typechange(c: &WorktreeChange) -> bool {
c.flags.is_some_and(|f| f.is_typechange())
} Try / catch
// fall back to whole-file on this specific bail
if let Err(e) = discard_workspace_changes(...) {
if e.to_string().contains("Type-changed") { whole_file_discard(change)?; } else { return Err(e); }
} Prevention
- Check is_typechange() flags before entering any hunk-based code path
- Surface chmod/symlink changes as whole-file changes in the UI
- Test discard flows against repos containing symlinks and executable-bit changes
When it happens
Trigger: Calling discard_workspace_changes with a change whose flags include is_typechange() while requesting hunk-scoped restoration; typically a path whose git entry kind changed between Blob, BlobExecutable, Link, etc.
Common situations: A user chmod +x'd a file, or replaced a regular file with a symlink (common on macOS/Linux), then tries to discard selected lines instead of the whole change. Tools that sync permission/symlink changes from other systems.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- `but setup` cannot run from a linked worktree; run it from…
- Cannot currently work in repositories without a worktree
- Cannot currently work in repositories without a worktree
- Cannot hash directory entries that aren't files or symlinks
- Cannot restore branch
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/459f05af57bac379.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-workspace/src/tree_manipulation/discard_worktree_changes.rs:156
match wt_change.status {
TreeStatus::Addition { .. } | TreeStatus::Deletion { .. } => {
bail!(
"Deletions or additions aren't well-defined for hunk-based operations - use the whole-file mode instead: '{}'",
wt_change.path
)
}
TreeStatus::Modification {
previous_state,
flags,
..
}
| TreeStatus::Rename {
previous_state,
flags,
..
} => {
if flags.is_some_and(|f| f.is_typechange()) {
bail!(
"Type-changed items can't be discard by hunks - use the whole-file mode instead"
)
}
hunk::restore_state_to_worktree(
wt_change,
previous_state,
&mut spec.hunk_headers,
&mut path_check,
&mut pipeline,
&index,
context_lines,
)?;
if !spec.hunk_headers.is_empty() {
dropped.push(spec);
continue;
}
}
}View on GitHub (pinned to 58e5313667)