When working with Laravel's filesystem abstraction (Storage), you might run into this dreaded exception:

League\Flysystem\UnableToListContents
Unable to list contents for '', deep listing
Reason: Unsupported symbolic link encountered

This happens when you call:

$files = Storage::disk('local')->allFiles();

…and one of the directories in your storage disk contains a symbolic link. Flysystem (used under the hood by Laravel) does not support following symlinks for deep listings, as a safeguard against infinite loops or security issues.

To work around this without any external dependencies, use native PHP iterators:

use Illuminate\Support\Facades\Storage;

$disk = Storage::disk('local');
$rootPath = $disk->path(''); // Absolute path to the disk's root

$files = [];

$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootPath, FilesystemIterator::SKIP_DOTS),
    RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($iterator as $file) {
    if ($file->isLink()) {
        // ❌ Skip symlinks
        continue;
    }

    if ($file->isFile()) {
        // Get the path relative to the disk root
        $relativePath = ltrim(str_replace($rootPath, '', $file->getPathname()), '/\\');
        $files[] = $relativePath;
    }
}

Explanation:

  • RecursiveDirectoryIterator: Walks the directory tree.
  • RecursiveIteratorIterator: Flattens it to a list of files.
  • FilesystemIterator::SKIP_DOTS: Skips . and .. entries.
  • $file->isLink(): Ensures symbolic links are skipped.
  • str_replace() + ltrim(): Converts absolute path back to Laravel's relative path for later use with Storage::disk()->get($path).

Flysystem's allFiles() is handy, but not symlink-safe. By using native PHP iterators, you can safely walk your directories, skip symbolic links, and keep your Laravel app stable β€” all without installing a single package.