{"record":{"id":"a22f8c1284273614","repo":"GitoxideLabs/gitoxide","slug":"source-or-destination-is-binary-and-we-can-t-diff","errorCode":null,"errorMessage":"Source or destination is binary and we can't diff that","messagePattern":"Source or destination is binary and we can't diff that","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitoxide-core/src/repository/diff.rs","lineNumber":197,"sourceCode":"    resource_cache.set_resource(\n        new_blob_id,\n        gix::object::tree::EntryKind::Blob,\n        new_path.as_ref(),\n        gix::diff::blob::ResourceKind::NewOrDestination,\n        &repo.objects,\n    )?;\n\n    let outcome = resource_cache.prepare_diff()?;\n\n    use gix::diff::blob::platform::prepare_diff::Operation;\n\n    let algorithm = match outcome.operation {\n        Operation::InternalDiff { algorithm } => algorithm,\n        Operation::ExternalCommand { .. } => {\n            unreachable!(\"We disabled that\")\n        }\n        Operation::SourceOrDestinationIsBinary => {\n            anyhow::bail!(\"Source or destination is binary and we can't diff that\")\n        }\n    };\n\n    let interner = gix::diff::blob::InternedInput::new(\n        tokens_for_diffing(outcome.old.data.as_slice().unwrap_or_default()),\n        tokens_for_diffing(outcome.new.data.as_slice().unwrap_or_default()),\n    );\n\n    let diff = gix::diff::blob::diff_with_slider_heuristics(algorithm, &interner);\n    let rendered = gix::diff::blob::UnifiedDiff::new(\n        &diff,\n        &interner,\n        gix::diff::blob::unified_diff::ConsumeBinaryHunk::new(BString::default(), \"\\n\"),\n        gix::diff::blob::unified_diff::ContextSize::symmetrical(3),\n    )\n    .consume()?;\n    write!(out, \"{rendered}\")?;\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gitoxide-core/src/repository/diff.rs#L179-L215","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet outcome = repo.diff_tree_to_tree(...)  // hits binary pair\n// after\nif outcome.operation == Operation::SourceOrDestinationIsBinary {\n    eprintln!(\"skipping binary file\");\n} else { /* proceed with diff */ }","handlingStrategy":"fallback","validationCode":"fn looks_binary(data: &[u8]) -> bool {\n    data.contains(&0) || data.starts_with(&[0xFF, 0xFE])\n}\nif looks_binary(&old_data) || looks_binary(&new_data) {\n    eprintln!(\"skipping binary file\");\n    return Ok(());\n}","typeGuard":null,"tryCatchPattern":"match outcome.operation {\n    Operation::SourceOrDestinationIsBinary => {\n        eprintln!(\"binary file, using fallback compare\");\n        // fallback: report as binary-changed or use a binary diff\n    }\n    op => { /* text diff */ }\n}","preventionTips":["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"],"tags":["diff","binary-files","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}