GitoxideLabs/gitoxide · error
could not read reference to pin
Error message
could not read reference to pin: {err} What it means
While building the set of references to pin in the ref-tree, iteration over `refs.all()` returned a per-reference error that was not the tolerated "missing ref" condition. Any other I/O or parse failure reading a reference is converted to this anyhow error wrapping the original `err`.
Solutions
- Fix the underlying ref error reported in `{err}` — check permissions and file contents under `.git/refs` and `packed-refs`.
- Stop concurrent git processes (gc, pack-refs, fetch) that may be rewriting refs, then retry.
- Run `git fsck` to detect and repair corrupted reference files.
- If a genuinely unreadable ref should be skipped, extend the match arm to log and `continue` instead of returning, mirroring the `is_missing_ref` arm.
Example fix
// before
Err(err) => return Err(anyhow::anyhow!("could not read reference to pin: {err}")),
// after
Err(err) if crate::history::is_missing_ref(&*err) => continue,
Err(err) => {
eprintln!("skipping unreadable reference: {err}");
continue;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Probe ref readability before pinning:
let readable = std::fs::read_dir(repo_path.join("refs")).is_ok()
&& std::fs::read(repo_path.join("packed-refs")).is_ok(); Try / catch
match pin_selection(&repo, ...) {
Err(e) if e.to_string().starts_with("could not read reference to pin") => {
eprintln!("A ref file is unreadable/corrupt: {e}; run git fsck and check permissions");
}
res => res?,
} Prevention
- Avoid running git gc/pack-refs concurrently with the TUI session
- Keep `.git/refs` and `packed-refs` readable by the current user
- Run `git fsck` periodically to catch corrupted refs early
- Tolerate-and-log unreadable refs if the UI should degrade gracefully
When it happens
Trigger: Calling the ref-tree pinning path (ref_tree.rs:829) when a reference file cannot be read — e.g. a packed-refs entry is malformed, the loose ref file exists but is unreadable, or a filesystem/permission error occurs mid-iteration — and the error does not match `crate::history::is_missing_ref`.
Common situations: Concurrent `git gc`/`git pack-refs` rewriting refs while the TUI is open; permission problems on `.git/refs` or `packed-refs`; a corrupted or hand-edited ref file containing a non-OID value.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- BUG: Invalid state: we never discard only our file, always…
- this one only happens on iteration creation
- Refusing to checkout index into existing directory
- Failed to handle repositories
- could not read review reference
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/8d37d8bcd564dd32.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/ref_tree.rs:829
pin_references_reporting(repository, id, kinds).map(|(pins, _changes)| pins)
}
pub(crate) fn pin_references_reporting(
repository: &gix::Repository,
id: ObjectId,
kinds: &[DecorationKind],
) -> anyhow::Result<(Vec<crate::history::Pin>, Vec<crate::edit::undo::RefChange>)> {
let mut names = Vec::new();
for reference in repository
.references()
.context("could not open references while pinning the ref-tree selection")?
.all()
.context("could not iterate references while pinning the ref-tree selection")?
{
let mut reference = match reference {
Ok(reference) => reference,
Err(err) if crate::history::is_missing_ref(&*err) => continue,
Err(err) => return Err(anyhow::anyhow!("could not read reference to pin: {err}")),
};
let name = reference.name().to_owned();
let Some(kind) = pinnable_kind(crate::history::decoration_kind(name.as_bstr())) else {
continue;
};
if !kinds.contains(&kind) {
continue;
}
let Ok(target) = reference.peel_to_id() else {
continue;
};
if target.as_ref() != id {
continue;
}
names.push(name);
}
names.sort();
names.dedup();View on GitHub (pinned to e73179060b)