GitoxideLabs/gitoxide · warning · anyhow::Error

{message}

Error message

{message}

What it means

The file change being diffed carries no usable content (e.g. the file was untracked, replaced by a submodule change, or its blob could not be loaded), and the FileChange enum conveys that as a message string. The diff preparation propagates it as a bail with that message. It is a controlled early-exit, not an internal failure.

Solutions

  1. Match on FileChange::Unavailable in the caller and skip or render a placeholder instead of asking for a diff.
  2. Verify the object exists (gix::Repository::find_object) before requesting a diff for the path.
  3. For submodule/type changes, use a change-type presentation rather than a line diff.
  4. Repair the repository (git fsck) if the blob is genuinely missing.

Example fix

// before
let prepared = prepare_file_diff(repo, &change, &path, true)?;
// after
let prepared = match &change {
    FileChange::Unavailable(msg) => { eprintln!("skipping: {msg}"); continue; }
    _ => prepare_file_diff(repo, &change, &path, true)?,
};
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(change, FileChange::Unavailable(_)) { /* skip diff */ }

Type guard

fn is_unavailable(change: &FileChange) -> bool {
    matches!(change, FileChange::Unavailable(_))
}

Try / catch

match prepare_file_diff(repo, &change, &path, true) {
    Err(err) if err.to_string() == unavailable_msg => skip_or_placeholder(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling the file-diff preparation (prepare of PreparedFileDiff) with a FileChange::Unavailable variant, which occurs when git reports an unavailable/irrelevant change for the path (e.g. type change to submodule, intent-to-add, missing object).

Common situations: Diffing a working-tree status entry for a submodule or untracked-but-staged path; repository with missing blob objects; status output including FileChange::Unavailable entries.

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/0ae56a2491731f74. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/lib.rs:5112

fn prepare_file_diff_with_repository(
    repository: &gix::Repository,
    change: &FileChange,
    path: &PathChange,
) -> Result<FileDiff> {
    match prepare_file_diff_content(repository, change, path, false)? {
        PreparedFileDiff::External(command, _) => Ok(FileDiff::External(command)),
        PreparedFileDiff::BuiltIn(diff, _) => prepare_pager(repository, diff),
    }
}

fn prepare_file_diff_content(
    repository: &gix::Repository,
    change: &FileChange,
    path: &PathChange,
    count_lines: bool,
) -> Result<PreparedFileDiff> {
    if let FileChange::Unavailable(message) = change {
        anyhow::bail!("{message}");
    }
    let global_command = repository
        .config_snapshot()
        .trusted_program(gix::config::tree::Diff::EXTERNAL)
        .map(gix::path::os_string_into_bstring)
        .transpose()
        .context("external diff command is not representable on this platform")?;
    let mut resources = match change {
        FileChange::Tree(_) => repository
            .diff_resource_cache(
                gix::diff::blob::pipeline::Mode::ToGitUnlessBinaryToTextIsPresent,
                Default::default(),
            )
            .context("could not initialize file diff")?,
        FileChange::Worktree { .. } => worktree_diff_cache(
            repository,
            gix::diff::blob::pipeline::Mode::ToGitUnlessBinaryToTextIsPresent,
        )?

View on GitHub (pinned to e73179060b)