uutils/coreutils · error · io::Error

Too many levels of symbolic links

Error message

Too many levels of symbolic links

What it means

When du is asked to fully dereference symlinks (--dereference / -L) it follows them, and to avoid infinite loops it enforces MAX_SYMLINK_DEPTH. Exceeding the limit yields this InvalidData error wrapped with a 'cannot access' context for the offending path. It corresponds to the classic ELOOP condition, implemented manually for symlink chains.

Source

Thrown at src/uu/du/src/du.rs:664

        'file_loop: for f in read {
            match f {
                Ok(entry) => {
                    let entry_path = entry.path();

                    // Check if this is a symlink when using -L
                    let mut current_symlink_depth = symlink_depth;
                    let is_symlink = match entry.file_type() {
                        Ok(ft) => ft.is_symlink(),
                        Err(_) => false,
                    };

                    if is_symlink && options.dereference == Deref::All {
                        // Increment symlink depth
                        current_symlink_depth += 1;

                        // Check symlink depth limit
                        if current_symlink_depth > MAX_SYMLINK_DEPTH {
                            print_tx.send(Err(io::Error::new(
                                io::ErrorKind::InvalidData,
                                "Too many levels of symbolic links",
                            ).map_err_context(
                                || translate!("du-error-cannot-access", "path" => entry_path.quote()),
                            )))?;
                            continue 'file_loop;
                        }
                    }

                    match Stat::new(&entry_path, Some(&entry), options) {
                        Ok(this_stat) => {
                            // Check if symlink with -L points to an ancestor (cycle detection)
                            if is_symlink
                                && options.dereference == Deref::All
                                && this_stat.metadata.is_dir()
                                && let Some(inode) = this_stat.inode
                                && ancestors.contains(&inode)
                            {

View on GitHub (pinned to 85295bbf78)

Solutions

  1. Find and remove the symlink loop: `namei -l <path>` or `find -L <dir> -type l` to locate the cycle
  2. Run du without -L (default -P behavior) so symlinks are not followed
  3. Increase your tolerance by resolving deep chains into direct paths before du
  4. Exclude loop-containing directories from the du invocation

Example fix

// before
du -L -sh suspicious-dir/
// after
find -L suspicious-dir/ -type l  # locate the loop, fix it
du -sh suspicious-dir/
Defensive patterns

Strategy: validation

Validate before calling

// detect symlink cycles before du -L
find -L /path -type l 2>/dev/null   # lists paths where traversal looped
namei -l /path/to/entry              # shows each symlink hop

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: du -L encounters a chain of more than MAX_SYMLINK_DEPTH nested symlinks, typically a symlink loop (a -> b -> a) or a very deep symlink hierarchy.

Common situations: Cyclic symlinks created by misconfigured deployments (current -> current), symlink loops in build outputs, bind-mounted or synced directories (Dropbox/rsync) containing cycles.

Related errors


AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31). Data as JSON: /api/errors/657dbad60b010c15. Report an issue: GitHub.