Lightning-AI/pytorch-lightning · error · ValueError

f"`{hook_name}` is not a shared hook within `LightningModule

Error message

f"`{hook_name}` is not a shared hook within `LightningModule` and `LightningDataModule`." f" Valid hooks are {self._valid_hooks}."

What it means

ValueError from _DataFetcher/get_instance: the requested hook_name is not one of the shared hooks Lightning forwards between LightningModule and LightningDataModule — only 'on_before_batch_transfer', 'transfer_batch_to_device', 'on_after_batch_transfer' are valid. Calling get_instance with any other hook name is an internal API misuse.

Source

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

    1. the :class:`~lightning.pytorch.core.LightningModule`,
    2. the :class:`~lightning.pytorch.core.datamodule.LightningDataModule`,

    Arguments:
        model: A ``LightningModule``
        datamodule: A ``LightningDataModule``

    """

    model: "pl.LightningModule"
    datamodule: Optional["pl.LightningDataModule"]
    _valid_hooks: tuple[str, ...] = field(
        default=("on_before_batch_transfer", "transfer_batch_to_device", "on_after_batch_transfer")
    )

    def get_instance(self, hook_name: str) -> Union["pl.LightningModule", "pl.LightningDataModule"]:
        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"

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Use only the three supported shared-hook names with get_instance
  2. Resolve other hooks directly on trainer.datamodule or trainer.lightning_module yourself
  3. Update custom code to current Lightning APIs after version changes

Example fix

# before
instance = fetcher.get_instance("train_dataloader")
# after
instance = fetcher.get_instance("transfer_batch_to_device")
# or directly:
dl = trainer.datamodule.train_dataloader() if trainer.datamodule else model.train_dataloader
Defensive patterns

Strategy: validation

Validate before calling

VALID = ("on_before_batch_transfer", "transfer_batch_to_device", "on_after_batch_transfer")
if hook_name not in VALID:
    raise ValueError(f"unsupported hook {hook_name}; resolve it on trainer.datamodule/lightning_module instead")

Type guard

def is_shared_hook(name: str) -> bool:
    return name in ("on_before_batch_transfer", "transfer_batch_to_device", "on_after_batch_transfer")

Prevention

When it happens

Trigger: Internal/advanced code calling _DataFetcher.get_instance("train_dataloader") or any hook outside the allowlist; custom forks or plugins invoking the connector's hook-resolution API with arbitrary hook names.

Common situations: Plugin/strategy code copied from older Lightning internals where the API accepted more names; monkeypatching or extending Lightning internals during research code.

Related errors


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