{"record":{"id":"d37eea2cb0b05c58","repo":"Lightning-AI/pytorch-lightning","slug":"you-have-overridden-hook-name-in-lightningmod","errorCode":null,"errorMessage":"You have overridden `{hook_name}` in `LightningModule` but have passed in a `LightningDataModule`. It will use the implementation from `LightningModule` instance.","messagePattern":"You have overridden `(.+?)` in `LightningModule` but have passed in a `LightningDataModule`\\. It will use the implementation from `LightningModule` instance\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lightning/pytorch/trainer/connectors/data_connector.py","lineNumber":378,"sourceCode":"        if hook_name not in self._valid_hooks:\n            raise ValueError(\n                f\"`{hook_name}` is not a shared hook within `LightningModule` and `LightningDataModule`.\"\n                f\" Valid hooks are {self._valid_hooks}.\"\n            )\n\n        if self.datamodule is None:\n            return self.model\n\n        if is_overridden(hook_name, self.datamodule):\n            if is_overridden(hook_name, self.model):\n                warning_cache.warn(\n                    f\"You have overridden `{hook_name}` in both `LightningModule` and `LightningDataModule`.\"\n                    \" It will use the implementation from `LightningDataModule` instance.\"\n                )\n            return self.datamodule\n\n        if is_overridden(hook_name, self.model):\n            warning_cache.warn(\n                f\"You have overridden `{hook_name}` in `LightningModule` but have passed in a\"\n                \" `LightningDataModule`. It will use the implementation from `LightningModule` instance.\"\n            )\n        return self.model\n\n\ndef _check_dataloader_iterable(\n    dataloader: object,\n    source: _DataLoaderSource,\n    trainer_fn: TrainerFn,\n) -> None:\n    if isinstance(dataloader, DataLoader):\n        # Fast path: `torch.utils.data.DataLoader` is always iterable, calling iter() would be expensive\n        return\n\n    try:\n        iter(dataloader)  # type: ignore[call-overload]\n    except TypeError:","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/trainer/connectors/data_connector.py#L360-L396","documentation":"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.","triggerScenarios":"Trainer(...).fit(model, datamodule=dm) where model defines train_dataloader but dm does not.","commonSituations":"Adding a datamodule for orchestration/defaults while keeping legacy dataloader methods in the model.","solutions":["Move the dataloader method into the DataModule for consistency","Or remove the datamodule argument if the model self-provides data","Accept the warning if the intent is model-supplied data"],"exampleFix":"# before\nclass M(LightningModule):\n    def train_dataloader(self): return make_loader()\ntrainer.fit(M(), datamodule=dm)\n# after\nclass DM(LightningDataModule):\n    def train_dataloader(self): return make_loader()\ntrainer.fit(M(), datamodule=DM())","handlingStrategy":"validation","validationCode":"from lightning.pytorch.utilities.model_helpers import is_overridden\nif is_overridden('train_dataloader', model) and dm is not None:\n    print('model hook will be used; datamodule ignored for this hook')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Choose one owner for data loading per hook","Prefer the DataModule for multi-run data pipelines"],"tags":["datamodule","hook-conflict","data-loading","lightning"],"backgroundTag":"duplicate-hook-override","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}