Lightning-AI/pytorch-lightning · warning
train_dataloader yielded None. If this was on purpose, ignor
Error message
train_dataloader yielded None. If this was on purpose, ignore this warning...
What it means
Training epoch loop warns when the train dataloader yields None for a batch (and dataloader_iter isn't being used). The batch is treated as absent — hooks and optimization are skipped for it.
Source
Thrown at src/lightning/pytorch/loops/training_epoch_loop.py:331
# fetcher state so that the batch_idx is correct after restarting
batch_idx = self.batch_idx + 1
# Note: `is_last_batch` is not yet determined if data fetcher is a `_DataLoaderIterDataFetcher`
self.batch_progress.is_last_batch = data_fetcher.done
trainer = self.trainer
if not using_dataloader_iter:
batch = trainer.precision_plugin.convert_input(batch)
batch = trainer.lightning_module._on_before_batch_transfer(batch, dataloader_idx=0)
batch = call._call_strategy_hook(trainer, "batch_to_device", batch, dataloader_idx=0)
self.batch_progress.increment_ready()
trainer._logger_connector.on_batch_start(batch)
batch_output: _BATCH_OUTPUTS_TYPE = None # for mypy
should_skip_rest_of_epoch = False
if batch is None and not using_dataloader_iter:
self._warning_cache.warn("train_dataloader yielded None. If this was on purpose, ignore this warning...")
else:
# hook
call._call_callback_hooks(trainer, "on_train_batch_start", batch, batch_idx)
response = call._call_lightning_module_hook(trainer, "on_train_batch_start", batch, batch_idx)
call._call_strategy_hook(trainer, "on_train_batch_start", batch, batch_idx)
should_skip_rest_of_epoch = response == -1
# Signal this is the last batch for the current epoch
if should_skip_rest_of_epoch:
self.batch_progress.increment_by(0, is_last_batch=True)
else:
self.batch_progress.increment_started()
kwargs = (
self._build_kwargs(OrderedDict(), batch, batch_idx)
if not using_dataloader_iter
else OrderedDict(any=dataloader_iter)
)
with trainer.profiler.profile("run_training_batch"):View on GitHub (pinned to 9fed5c27d2)
Solutions
- Filter out invalid samples in the Dataset instead of returning None
- Use a collate_fn that skips or replaces None items
- If intentional (sparse batches), ignore the warning
Example fix
# before
class DS(Dataset):
def __getitem__(self, i):
if bad(i):
return None
return x[i]
# after
class DS(Dataset):
def __getitem__(self, i):
if bad(i):
return self.__getitem__(i + 1) # or prefilter indices
return x[i] Defensive patterns
Strategy: validation
Validate before calling
batch = next(iter(train_dl)) assert batch is not None, 'dataloader yields None; fix dataset/collate'
Type guard
def dataset_yields_valid(ds) -> bool:
return all(ds[i] is not None for i in range(min(5, len(ds)))) Prevention
- Never return None from __getitem__; filter indices instead
- Test one batch from each dataloader in CI
When it happens
Trigger: A train_dataloader/dataset whose __getitem__ returns None (e.g. collate producing None, or a filter that returns None instead of skipping), or a custom iterator yielding None.
Common situations: Data cleaning code returning None for bad samples; IterableDataset with continue-style logic that still yields None.
Related errors
- You seem to have configured a sampler in your DataLoader whi
- f"An invalid dataloader was passed to `Trainer.{trainer_fn.v
- f"An invalid dataloader was passed to `Trainer.{trainer_fn.v
- Couldn't infer the batch indices fetched from your dataloade
- Received multiple values for {', '.join(duplicated_plugin_ke
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/f205147a65e34310.
Report an issue: GitHub.