GitoxideLabs/gitoxide · warning
no symlink related errors
Error message
no symlink related errors
What it means
A Rust `expect()` panic in the loose-refs iterator's `next()` (gix-ref/store/file/loose/iter.rs). When `walkdir` (or similar) reports a traversal error, the code converts it to an `io::Error` with `expect("no symlink related errors")`, reflecting the iterator's assumption that symlink-following loops cannot occur because the traversal does not follow symlinks. If the walker is configured (or a platform reports) a symlink-related error, this assumption breaks and the code panics instead of returning an error.
Solutions
- Remove or replace symlinks inside `.git/refs` with real directories or files before iterating loose refs.
- Do not enable `follow_links` on the walker used for loose-ref iteration.
- Check for and repair symlink loops (`find -type l` under `.git/refs`) and fix permissions on the refs tree.
- If plain repositories trigger it, report upstream with the fs layout — internal invariant violation.
Example fix
// before // refs/heads/master is a symlink loop -> walker error -> panic in next() // after $ find .git/refs -type l -delete # or replace symlinks with real files $ git fsck # verify repo health before iterating
Defensive patterns
Strategy: fallback
Validate before calling
// detect symlinks in refs tree before iterating
for entry in walkdir::WalkDir::new(".git/refs").follow_links(false) {
if entry.as_ref().ok()?.file_type().is_symlink() { return Err("symlink in refs"); }
} Try / catch
// pre-scan and refuse to iterate a refs tree containing symlinks
match contains_symlinks(".git/refs") {
true => return Err(anyhow!("refs tree contains symlinks; not supported")),
false => iterate_loose_refs(),
} Prevention
- Never place symlinks inside .git/refs
- Keep walker follow_links disabled
- Run git fsck after tools that may have replaced refs with symlinks
When it happens
Trigger: Traversing loose refs where the directory walker encounters a symlink-related error condition (symlink loop detection, permission errors surfaced through symlink handling), i.e. when symlinked directories exist under `refs/` and the iterator's no-symlink-following assumption is violated by configuration or platform behavior.
Common situations: Repositories whose `refs/` tree contains symbolic links (manually created, or some sync/backup tools replacing directories with symlinks); custom walker configurations enabling follow_links; unusual filesystems (network mounts) reporting symlink errors.
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
- ' ' is not a valid configuration key
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
- BUG: tries to obtain object id from symbolic target
- BUG: expected peeled reference target but found symbolic one
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/d80f2ad1d06a9451.
Report an issue: GitHub.
Appendix: source
Thrown at gix-ref/src/store/file/loose/iter.rs:82
};
if let Some(prefix) = &self.prefix
&& !full_name.starts_with(prefix)
{
continue;
}
if let Some(suffix) = &self.suffix
&& !full_name.ends_with(suffix)
{
continue;
}
if gix_validate::reference::name_partial(full_name.as_bstr()).is_ok() {
let name = FullName(full_name);
return Some(Ok((full_path, name)));
} else {
continue;
}
}
Err(err) => return Some(Err(err.into_io_error().expect("no symlink related errors"))),
}
}
None
}
}
impl file::Store {
/// Return an iterator over all loose references, notably not including any packed ones, in lexical order.
/// Each of the references may fail to parse and the iterator will not stop if parsing fails, allowing the caller
/// to see all files that look like references whether valid or not.
///
/// Reference files that do not constitute valid names will be silently ignored.
pub fn loose_iter(&self) -> std::io::Result<LooseThenPacked<'_, '_>> {
self.iter_packed(None)
}
/// Return an iterator over all loose references that start with the given `prefix`.
///View on GitHub (pinned to e73179060b)