GitoxideLabs/gitoxide · error
Source or destination is binary and we can't diff that
Error message
Source or destination is binary and we can't diff that
What it means
When diffing two blobs, `gix` detects whether the source or destination content is binary (e.g. contains NUL bytes or other non-text data). Since the text diffing machinery only works on tokenizable text, `Operation::SourceOrDestinationIsBinary` is returned and the CLI converts it into this error — git-like behavior of refusing to diff binary files.
Solutions
- Confirm the files you intend to diff are text (check for binary content, e.g. no NUL bytes)
- Use a diff tool that supports binary files (e.g. git's binary diff or a dedicated compare) instead of this text-diff command
- Set appropriate .gitattributes so binary files are marked and handled as such
- Strip or normalize the binary content (e.g. re-encode to UTF-8) before diffing
Example fix
// before
let outcome = repo.diff_tree_to_tree(...) // hits binary pair
// after
if outcome.operation == Operation::SourceOrDestinationIsBinary {
eprintln!("skipping binary file");
} else { /* proceed with diff */ } Defensive patterns
Strategy: fallback
Validate before calling
fn looks_binary(data: &[u8]) -> bool {
data.contains(&0) || data.starts_with(&[0xFF, 0xFE])
}
if looks_binary(&old_data) || looks_binary(&new_data) {
eprintln!("skipping binary file");
return Ok(());
} Try / catch
match outcome.operation {
Operation::SourceOrDestinationIsBinary => {
eprintln!("binary file, using fallback compare");
// fallback: report as binary-changed or use a binary diff
}
op => { /* text diff */ }
} Prevention
- Check for NUL bytes / use a binary-detection heuristic before text-diffing blobs
- Mark binary files in .gitattributes
- Handle Operation::SourceOrDestinationIsBinary explicitly in your match arms instead of assuming text
When it happens
Trigger: Calling `file` in gitoxide-core/src/repository/diff.rs on a pair of blobs where either the old or new object's buffer is classified as binary, producing `Operation::SourceOrDestinationIsBinary` in the diff outcome.
Common situations: Diffing images, compiled artifacts, or files with NUL bytes/odd encodings; a file saved in UTF-16 or with a stray NUL byte gets classified as binary even though it looks textual.
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
- a tree change cannot be amended from the worktree
- cannot spill an unmerged path
- copying a commit requires it to have exactly one parent
- review commits cannot be copied
- copying a commit cannot rewrite root or merge commits
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/a22f8c1284273614.
Report an issue: GitHub.
Appendix: source
Thrown at gitoxide-core/src/repository/diff.rs:197
resource_cache.set_resource(
new_blob_id,
gix::object::tree::EntryKind::Blob,
new_path.as_ref(),
gix::diff::blob::ResourceKind::NewOrDestination,
&repo.objects,
)?;
let outcome = resource_cache.prepare_diff()?;
use gix::diff::blob::platform::prepare_diff::Operation;
let algorithm = match outcome.operation {
Operation::InternalDiff { algorithm } => algorithm,
Operation::ExternalCommand { .. } => {
unreachable!("We disabled that")
}
Operation::SourceOrDestinationIsBinary => {
anyhow::bail!("Source or destination is binary and we can't diff that")
}
};
let interner = gix::diff::blob::InternedInput::new(
tokens_for_diffing(outcome.old.data.as_slice().unwrap_or_default()),
tokens_for_diffing(outcome.new.data.as_slice().unwrap_or_default()),
);
let diff = gix::diff::blob::diff_with_slider_heuristics(algorithm, &interner);
let rendered = gix::diff::blob::UnifiedDiff::new(
&diff,
&interner,
gix::diff::blob::unified_diff::ConsumeBinaryHunk::new(BString::default(), "\n"),
gix::diff::blob::unified_diff::ContextSize::symmetrical(3),
)
.consume()?;
write!(out, "{rendered}")?;
View on GitHub (pinned to e73179060b)