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

  1. Confirm the files you intend to diff are text (check for binary content, e.g. no NUL bytes)
  2. Use a diff tool that supports binary files (e.g. git's binary diff or a dedicated compare) instead of this text-diff command
  3. Set appropriate .gitattributes so binary files are marked and handled as such
  4. 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

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


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)