GitoxideLabs/gitoxide · error

find returned a cached commit, so we expect cache to be…

Error message

find returned a cached commit, so we expect cache to be present

What it means

This is an expect() panic in gix-blame's collect_parents: when the commit graph returns a CachedCommit variant, the function requires a parallel commit cache (Graph cache) to have been provided. The library assumes that whenever a cached commit is produced, the cache must exist; if the cache is None while the iterator yields CachedCommit, the assumption is violated and it panics instead of returning a recoverable error.

Solutions

  1. Ensure the commit cache is created and passed to the blame traversal whenever the graph may yield cached commits
  2. Inspect the call site in gix-blame/src/file/function.rs collect_parents and make cache retrieval fallible (return an Error) instead of expect
  3. Update gix-blame if this is a known bug fixed in a newer release
  4. File a bug with a reproduction, since a panic here indicates an internal invariant violation

Example fix

// before
let cache = cache
    .as_ref()
    .expect("find returned a cached commit, so we expect cache to be present");
// after
let cache = cache.as_ref().ok_or_else(|| {
    message("cached commit produced without a commit cache being present")
})?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before invoking blame internals, ensure a cache is supplied when cached commits are possible:
assert!(cache.is_some(), "commit cache must be provided for cached-commit traversal");

Type guard

fn cache_present(cache: &Option<Cache>) -> bool { cache.is_some() }

Try / catch

// Panics are not catchable safely in Rust; guard instead:
let cache = match cache.as_ref() {
    Some(c) => c,
    None => return Err(message("cached commit without cache")),
};

Prevention

When it happens

Trigger: Calling the blame file API with a commit iterator/graph configured so that Either::CachedCommit is produced while the `cache` parameter is None — e.g. a miswired internal combination of traversal options where the cache handle is not passed down.

Common situations: Hit by library maintainers or users constructing the blame traversal directly with inconsistent graph/cache arguments, or after an upstream refactor changed how the commit cache is threaded through, rather than by ordinary end users of the porcelain API.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/372d0a3fd4ef367c. Report an issue: GitHub.

Appendix: source

Thrown at gix-blame/src/file/function.rs:873

    )?;
    stats.trees_decoded -= 1;
    Ok(res.map(|e| e.oid))
}

type ParentIds = SmallVec<[(gix_hash::ObjectId, i64); 2]>;

fn collect_parents(
    commit: gix_traverse::commit::Either<'_, '_>,
    odb: &impl gix_object::Find,
    cache: Option<&gix_commitgraph::Graph>,
    buf: &mut Vec<u8>,
) -> Result<ParentIds, Error> {
    let mut parent_ids: ParentIds = Default::default();
    match commit {
        gix_traverse::commit::Either::CachedCommit(commit) => {
            let cache = cache
                .as_ref()
                .expect("find returned a cached commit, so we expect cache to be present");
            for parent_pos in commit.iter_parents() {
                let parent = cache.commit_at(parent_pos?);
                parent_ids.push((parent.id().to_owned(), parent.committer_timestamp() as i64));
            }
        }
        gix_traverse::commit::Either::CommitRefIter(commit_ref_iter) => {
            for id in commit_ref_iter.parent_ids() {
                let parent = odb.find_commit_iter(id.as_ref(), buf).ok();
                let parent_commit_time = parent
                    .and_then(|parent| parent.committer().ok().map(|committer| committer.seconds()))
                    .unwrap_or_default();
                parent_ids.push((id, parent_commit_time));
            }
        }
    }
    Ok(parent_ids)
}

View on GitHub (pinned to e73179060b)