Introduction
tf.keras.utils.image_dataset_from_directory loads images from a directory tree into a tf.data.Dataset, automatically labeling them by subfolder name. When it reports "Found 0 files," the cause is almost always a wrong directory path, unsupported file extensions, an incorrect directory structure (images sitting directly in the root instead of class subfolders), or file permission issues. Fixing the directory layout and verifying the path resolves the problem in most cases.
Expected Directory Structure
The function expects images organized into class subdirectories:
1dataset/
2├── cats/
3│ ├── cat_001.jpg
4│ ├── cat_002.png
5│ └── cat_003.jpeg
6└── dogs/
7 ├── dog_001.jpg
8 ├── dog_002.png
9 └── dog_003.jpeg
1import tensorflow as tf
2
3dataset = tf.keras.utils.image_dataset_from_directory(
4 'dataset/',
5 image_size=(224, 224),
6 batch_size=32
7)
8# Found 6 files belonging to 2 classes.
If images are placed directly in the root folder without subdirectories, the function finds 0 files:
1dataset/ # WRONG — no class subdirectories
2├── img_001.jpg
3├── img_002.jpg
4└── img_003.jpg
Fix 1: Correct the Directory Path
The most common cause is a wrong or relative path:
1# Wrong — relative path may not resolve correctly
2dataset = tf.keras.utils.image_dataset_from_directory('data/train')
3
4# Fix — use an absolute path or verify the working directory
5import os
6print(os.getcwd()) # Check current working directory
7print(os.listdir('data/train')) # Verify contents
8
9# Use absolute path
10dataset = tf.keras.utils.image_dataset_from_directory(
11 '/home/user/project/data/train',
12 image_size=(224, 224),
13 batch_size=32
14)
Fix 2: Add Class Subdirectories
If all images are in a single folder, move them into class subdirectories:
1import os
2import shutil
3
4# Organize flat images into class folders based on filename prefix
5source = 'dataset/'
6for filename in os.listdir(source):
7 if filename.startswith('cat'):
8 dest = os.path.join(source, 'cats')
9 elif filename.startswith('dog'):
10 dest = os.path.join(source, 'dogs')
11 else:
12 continue
13 os.makedirs(dest, exist_ok=True)
14 shutil.move(os.path.join(source, filename), os.path.join(dest, filename))
For binary classification with a single class, use labels='inferred' with the label_mode parameter, or set labels=None for unlabeled data:
1# Single class — put all images in one subfolder
2dataset = tf.keras.utils.image_dataset_from_directory(
3 'dataset/',
4 labels=None, # No labels needed
5 image_size=(224, 224)
6)
Fix 3: Check Supported File Extensions
By default, the function looks for .jpg, .jpeg, .png, .bmp, and .gif files. Other formats like .tiff, .webp, or .svg are silently skipped:
1# Check what files are in the directory
2import os
3for root, dirs, files in os.walk('dataset/'):
4 for f in files:
5 ext = os.path.splitext(f)[1].lower()
6 print(f"{f} -> {ext}")
7
8# If files have wrong extensions, rename them
9for root, dirs, files in os.walk('dataset/'):
10 for f in files:
11 if f.endswith('.tiff'):
12 old = os.path.join(root, f)
13 new = os.path.join(root, f.replace('.tiff', '.png'))
14 from PIL import Image
15 Image.open(old).save(new)
Fix 4: Handle Hidden Files and Corrupted Images
Hidden files (like .DS_Store on macOS) and corrupted images can cause issues:
1# Remove hidden files
2import os
3for root, dirs, files in os.walk('dataset/'):
4 for f in files:
5 if f.startswith('.'):
6 os.remove(os.path.join(root, f))
7 print(f"Removed hidden file: {f}")
8
9# Validate all images can be opened
10from PIL import Image
11for root, dirs, files in os.walk('dataset/'):
12 for f in files:
13 path = os.path.join(root, f)
14 try:
15 img = Image.open(path)
16 img.verify()
17 except Exception as e:
18 print(f"Corrupted: {path} — {e}")
Fix 5: Verify File Permissions
On Linux/macOS, restrictive permissions prevent the function from reading files:
1# Check permissions
2ls -la dataset/cats/
3
4# Fix permissions
5chmod -R 644 dataset/
6chmod -R +X dataset/ # Add execute to directories only
1import os
2# Programmatic check
3for root, dirs, files in os.walk('dataset/'):
4 for f in files:
5 path = os.path.join(root, f)
6 if not os.access(path, os.R_OK):
7 print(f"Cannot read: {path}")
Debugging Checklist
1import os
2import tensorflow as tf
3
4data_dir = 'dataset/'
5
6# 1. Does the path exist?
7print(f"Path exists: {os.path.exists(data_dir)}")
8
9# 2. What subdirectories exist?
10subdirs = [d for d in os.listdir(data_dir)
11 if os.path.isdir(os.path.join(data_dir, d))]
12print(f"Subdirectories: {subdirs}")
13
14# 3. How many images per subdirectory?
15for d in subdirs:
16 files = os.listdir(os.path.join(data_dir, d))
17 image_files = [f for f in files
18 if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
19 print(f" {d}: {len(image_files)} images")
20
21# 4. Try loading
22dataset = tf.keras.utils.image_dataset_from_directory(
23 data_dir,
24 image_size=(224, 224),
25 batch_size=32
26)
Common Pitfalls
Images in root directory without class subfolders: The function requires at least one level of subdirectories for class labels. Place images inside named subfolders, or use labels=None for unlabeled datasets.
Using the deprecated tf.keras.preprocessing path: In TensorFlow 2.9+, use tf.keras.utils.image_dataset_from_directory instead of tf.keras.preprocessing.image_dataset_from_directory, which is deprecated.
Relative paths resolve against the wrong directory: Jupyter notebooks and scripts may have different working directories. Use os.path.abspath() to verify the full path before passing it.
Uppercase file extensions not recognized: Files named image.JPG or photo.PNG are supported (the function is case-insensitive), but corrupted extensions like .jpg_ or .jpeg2 are not.
Symlinks or mounted drives not followed: On some systems, symbolic links or network-mounted directories may not be traversed. Copy the files locally or verify the symlinks resolve correctly.
Summary
image_dataset_from_directory requires images in class subdirectories, not directly in the root folder
Use absolute paths or verify os.getcwd() to ensure the path resolves correctly
Only .jpg, .jpeg, .png, .bmp, and .gif extensions are supported by default
Remove hidden files (.DS_Store) and validate images with PIL before loading
Use the debugging checklist to systematically identify why 0 files are found