GitoxideLabs/gitoxide · error · anyhow::Error

could not read reference

Error message

could not read reference: {err}

What it means

`loaded_graph` iterates all references to build a history graph; each individual reference read may fail (e.g. the ref points to a missing or non-commit object, or the ref file is corrupt). Such per-reference errors are wrapped as "could not read reference: {err}". Note a missing HEAD short-circuits to an empty graph and does not trigger this.

Solutions

  1. Identify the broken ref from the inner error and delete or repair it (git update-ref -d)
  2. Run `git fsck` to find dangling/corrupt references
  3. Re-pack refs (git pack-refs --all) to rebuild packed-refs
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify all refs resolve to existing objects
for r in repo.references()?.all()? {
    let r = r.map_err(|e| e)?; // surface broken refs before graph building
    let _ = r.try_id()?;
}

Try / catch

match loaded_graph(&repo) {
    Ok(g) => g,
    Err(e) if e.to_string().starts_with("could not read reference") => {
        eprintln!("run git fsck and repair broken refs");
        HistoryGraph::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling edit_graph_ignores_refs_that_do_not_point_to_commits / loaded_graph when `repo.references()?.all()?` yields an Err for some reference — dangling ref to a pruned object, corrupt packed-refs entry, or reflog/oid decode failure.

Common situations: Repos with stale refs after force-pushes and gc; refs pointing to objects deleted by aggressive pruning; corruption from interrupted operations.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at gix-tix/src/edit/mod.rs:11

use std::{io::Write, process::Command};

use anyhow::{Context, Result};

pub(super) fn loaded_graph(repo: &gix::Repository) -> Result<crate::history::HistoryGraph> {
    if repo.head_id().is_err() {
        return Ok(crate::history::HistoryGraph::default());
    }
    let mut revisions = Vec::new();
    for reference in repo.references()?.all()? {
        let reference = reference.map_err(|err| anyhow::anyhow!("could not read reference: {err}"))?;
        if reference.name().as_bstr().starts_with(crate::history::STASH_PREFIX)
            || reference
                .name()
                .as_bstr()
                .starts_with(crate::history::REVIEW_STASH_PREFIX)
            || undo::is_queue_ref(reference.name().as_bstr())
        {
            continue;
        }
        let Some(id) = reference.try_id() else { continue };
        if reference.name().as_bstr() == b"HEAD"
            || repo
                .find_header(id)
                .context("could not inspect reference target")?
                .kind()
                != gix::object::Kind::Commit
        {
            continue;

View on GitHub (pinned to e73179060b)