uutils/coreutils · error · Error
Too many levels of symbolic links
Error message
Too many levels of symbolic links
What it means
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).
Source
Thrown at src/uucore/src/lib/features/fs.rs:429
if res_mode == ResolveMode::None {
continue;
}
match resolve_symlink(&result) {
Ok(Some(link_path)) => {
for link_part in link_path.components().rev() {
parts.push_front(link_part.into());
}
if followed_symlinks < SYMLINKS_TO_LOOK_FOR_LOOPS {
followed_symlinks += 1;
} else {
let file_info =
FileInformation::from_path(result.parent().unwrap(), false).unwrap();
let mut path_to_follow = PathBuf::new();
for part in &parts {
path_to_follow.push(part.as_os_str());
}
if !visited_files.insert((file_info, path_to_follow)) {
return Err(Error::new(
ErrorKind::InvalidInput,
"Too many levels of symbolic links",
)); // TODO use ErrorKind::FilesystemLoop when stable
}
}
result.pop();
}
Err(e)
if (miss_mode == MissingHandling::Existing
|| (miss_mode == MissingHandling::Normal && !parts.is_empty())) =>
{
return Err(e);
}
_ => {}
}
}
// raise Not a directory if required
match miss_mode {View on GitHub (pinned to 85295bbf78)
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
Example fix
# before ln -s ../b a; ln -s ../a b # cycle # after ln -sfn /real/target a # point at a real file/dir
Defensive patterns
Strategy: try-catch
Validate before calling
fn detects_loop(root: &Path, depth_limit: usize) -> bool {
let mut seen = std::collections::HashSet::new();
let mut cur = root.to_path_buf();
for _ in 0..depth_limit {
if cur.is_file() { return false; }
if std::fs::read_link(&cur).is_ok() {
let canon = std::fs::canonicalize(&cur);
if canon.is_err() { return true; }
if !seen.insert(canon.unwrap()) { return true; }
}
if !cur.pop() { break; }
}
false
} Type guard
fn is_symlink_loop_err(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::InvalidInput
&& e.to_string().contains("Too many levels of symbolic links")
} Try / catch
match uucore::fs::canonicalize(p) {
Err(e) if is_symlink_loop_err(&e) => {
eprintln!("symlink loop at {}", p.display());
skip(p);
}
other => other?,
} Prevention
- Run find -L or namei to audit symlink trees
- Avoid hand-crafted relative symlink chains
- Detect loops before recursive directory walks
When it happens
Trigger: 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`.
Common situations: Cyclic symlinks created by mistake in build trees, symlink farms with hand-made loops, restoring backups that re-created looped links.
Related errors
- mv-error-dangling-symlink
- mv-error-inter-device-move-failed
- Too many levels of symbolic links
- Is a directory
- path component exists but is not a directory: {}
AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31).
Data as JSON: /api/errors/579b8d63168cb105.
Report an issue: GitHub.