{"record":{"id":"d80f2ad1d06a9451","repo":"GitoxideLabs/gitoxide","slug":"no-symlink-related-errors","errorCode":null,"errorMessage":"no symlink related errors","messagePattern":"no symlink related errors","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gix-ref/src/store/file/loose/iter.rs","lineNumber":82,"sourceCode":"                    };\n                    if let Some(prefix) = &self.prefix\n                        && !full_name.starts_with(prefix)\n                    {\n                        continue;\n                    }\n                    if let Some(suffix) = &self.suffix\n                        && !full_name.ends_with(suffix)\n                    {\n                        continue;\n                    }\n                    if gix_validate::reference::name_partial(full_name.as_bstr()).is_ok() {\n                        let name = FullName(full_name);\n                        return Some(Ok((full_path, name)));\n                    } else {\n                        continue;\n                    }\n                }\n                Err(err) => return Some(Err(err.into_io_error().expect(\"no symlink related errors\"))),\n            }\n        }\n        None\n    }\n}\n\nimpl file::Store {\n    /// Return an iterator over all loose references, notably not including any packed ones, in lexical order.\n    /// Each of the references may fail to parse and the iterator will not stop if parsing fails, allowing the caller\n    /// to see all files that look like references whether valid or not.\n    ///\n    /// Reference files that do not constitute valid names will be silently ignored.\n    pub fn loose_iter(&self) -> std::io::Result<LooseThenPacked<'_, '_>> {\n        self.iter_packed(None)\n    }\n\n    /// Return an iterator over all loose references that start with the given `prefix`.\n    ///","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-ref/src/store/file/loose/iter.rs#L64-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n// refs/heads/master is a symlink loop -> walker error -> panic in next()\n// after\n$ find .git/refs -type l -delete   # or replace symlinks with real files\n$ git fsck                         # verify repo health before iterating","handlingStrategy":"fallback","validationCode":"// detect symlinks in refs tree before iterating\nfor entry in walkdir::WalkDir::new(\".git/refs\").follow_links(false) {\n    if entry.as_ref().ok()?.file_type().is_symlink() { return Err(\"symlink in refs\"); }\n}","typeGuard":null,"tryCatchPattern":"// pre-scan and refuse to iterate a refs tree containing symlinks\nmatch contains_symlinks(\".git/refs\") {\n    true => return Err(anyhow!(\"refs tree contains symlinks; not supported\")),\n    false => iterate_loose_refs(),\n}","preventionTips":["Never place symlinks inside .git/refs","Keep walker follow_links disabled","Run git fsck after tools that may have replaced refs with symlinks"],"tags":["rust","panic","symlink","directory-traversal"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}