{"record":{"id":"579b8d63168cb105","repo":"uutils/coreutils","slug":"too-many-levels-of-symbolic-links-579b8d","errorCode":null,"errorMessage":"Too many levels of symbolic links","messagePattern":"Too many levels of symbolic links","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/uucore/src/lib/features/fs.rs","lineNumber":429,"sourceCode":"        if res_mode == ResolveMode::None {\n            continue;\n        }\n        match resolve_symlink(&result) {\n            Ok(Some(link_path)) => {\n                for link_part in link_path.components().rev() {\n                    parts.push_front(link_part.into());\n                }\n                if followed_symlinks < SYMLINKS_TO_LOOK_FOR_LOOPS {\n                    followed_symlinks += 1;\n                } else {\n                    let file_info =\n                        FileInformation::from_path(result.parent().unwrap(), false).unwrap();\n                    let mut path_to_follow = PathBuf::new();\n                    for part in &parts {\n                        path_to_follow.push(part.as_os_str());\n                    }\n                    if !visited_files.insert((file_info, path_to_follow)) {\n                        return Err(Error::new(\n                            ErrorKind::InvalidInput,\n                            \"Too many levels of symbolic links\",\n                        )); // TODO use ErrorKind::FilesystemLoop when stable\n                    }\n                }\n                result.pop();\n            }\n            Err(e)\n                if (miss_mode == MissingHandling::Existing\n                    || (miss_mode == MissingHandling::Normal && !parts.is_empty())) =>\n            {\n                return Err(e);\n            }\n            _ => {}\n        }\n    }\n    // raise Not a directory if required\n    match miss_mode {","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/uutils/coreutils/blob/85295bbf788bfd7a6926ba692031563504b304b7/src/uucore/src/lib/features/fs.rs#L411-L447","documentation":"The uucore `canonicalize` implementation resolves symlinks manually and tracks visited (file info, partial path) pairs. If the same target is encountered again, it concludes there is a symlink loop and returns `InvalidInput` with \"Too many levels of symbolic links\" (ErrorKind::FilesystemLoop is still unstable, hence the TODO).","triggerScenarios":"Calling `canonicalize` on a path whose symlink chain forms a cycle, e.g. `ln -s a b; ln -s b a`, or a self-referencing directory symlink like `ln -s . loop`.","commonSituations":"Cyclic symlinks created by mistake in build trees, symlink farms with hand-made loops, restoring backups that re-created looped links.","solutions":["Find and remove the looping symlink(s): `find -L . -type l` or `namei <path>`","Recreate the symlink pointing to the correct target","Use a filesystem loop detector before canonicalizing untrusted paths"],"exampleFix":"# before\nln -s ../b a; ln -s ../a b   # cycle\n# after\nln -sfn /real/target a       # point at a real file/dir","handlingStrategy":"try-catch","validationCode":"fn detects_loop(root: &Path, depth_limit: usize) -> bool {\n    let mut seen = std::collections::HashSet::new();\n    let mut cur = root.to_path_buf();\n    for _ in 0..depth_limit {\n        if cur.is_file() { return false; }\n        if std::fs::read_link(&cur).is_ok() {\n            let canon = std::fs::canonicalize(&cur);\n            if canon.is_err() { return true; }\n            if !seen.insert(canon.unwrap()) { return true; }\n        }\n        if !cur.pop() { break; }\n    }\n    false\n}","typeGuard":"fn is_symlink_loop_err(e: &std::io::Error) -> bool {\n    e.kind() == std::io::ErrorKind::InvalidInput\n        && e.to_string().contains(\"Too many levels of symbolic links\")\n}","tryCatchPattern":"match uucore::fs::canonicalize(p) {\n    Err(e) if is_symlink_loop_err(&e) => {\n        eprintln!(\"symlink loop at {}\", p.display());\n        skip(p);\n    }\n    other => other?,\n}","preventionTips":["Run find -L or namei to audit symlink trees","Avoid hand-crafted relative symlink chains","Detect loops before recursive directory walks"],"tags":["symlink","filesystem","canonicalize"],"backgroundTag":"symlink-loop","analyzedSha":"85295bbf788bfd7a6926ba692031563504b304b7","analyzedAt":"2026-08-31T11:11:36.175Z","contentChangedAt":"2026-08-31T11:11:36.175Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}