Lightning-AI/pytorch-lightning · warning

You have overridden ` ` in `LightningModule` but have…

Error message

You have overridden `{hook_name}` in `LightningModule` but have passed in a `LightningDataModule`. It will use the implementation from `LightningModule` instance.

What it means

Companion warning to the dual-override case: here only the LightningModule overrides the hook, but a LightningDataModule was also passed. The LightningModule's implementation is used and the datamodule's default is ignored.

Solutions

  1. Move the dataloader method into the DataModule for consistency
  2. Or remove the datamodule argument if the model self-provides data
  3. Accept the warning if the intent is model-supplied data

Example fix

# before
class M(LightningModule):
    def train_dataloader(self): return make_loader()
trainer.fit(M(), datamodule=dm)
# after
class DM(LightningDataModule):
    def train_dataloader(self): return make_loader()
trainer.fit(M(), datamodule=DM())
Defensive patterns

Strategy: validation

Validate before calling

from lightning.pytorch.utilities.model_helpers import is_overridden
if is_overridden('train_dataloader', model) and dm is not None:
    print('model hook will be used; datamodule ignored for this hook')

Prevention

When it happens

Trigger: Trainer(...).fit(model, datamodule=dm) where model defines train_dataloader but dm does not.

Common situations: Adding a datamodule for orchestration/defaults while keeping legacy dataloader methods in the model.

Related errors


AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28). Data as JSON: /api/errors/d37eea2cb0b05c58. Report an issue: GitHub.

Appendix: source

Thrown at src/lightning/pytorch/trainer/connectors/data_connector.py:378

        if hook_name not in self._valid_hooks:
            raise ValueError(
                f"`{hook_name}` is not a shared hook within `LightningModule` and `LightningDataModule`."
                f" Valid hooks are {self._valid_hooks}."
            )

        if self.datamodule is None:
            return self.model

        if is_overridden(hook_name, self.datamodule):
            if is_overridden(hook_name, self.model):
                warning_cache.warn(
                    f"You have overridden `{hook_name}` in both `LightningModule` and `LightningDataModule`."
                    " It will use the implementation from `LightningDataModule` instance."
                )
            return self.datamodule

        if is_overridden(hook_name, self.model):
            warning_cache.warn(
                f"You have overridden `{hook_name}` in `LightningModule` but have passed in a"
                " `LightningDataModule`. It will use the implementation from `LightningModule` instance."
            )
        return self.model


def _check_dataloader_iterable(
    dataloader: object,
    source: _DataLoaderSource,
    trainer_fn: TrainerFn,
) -> None:
    if isinstance(dataloader, DataLoader):
        # Fast path: `torch.utils.data.DataLoader` is always iterable, calling iter() would be expensive
        return

    try:
        iter(dataloader)  # type: ignore[call-overload]
    except TypeError:

View on GitHub (pinned to 9fed5c27d2)