Lightning-AI/pytorch-lightning · error · RuntimeError

You provided multiple `{stage.dataloader_prefix}_dataloader`

Error message

You provided multiple `{stage.dataloader_prefix}_dataloader`, but no `dataloader_idx` argument in `{type(pl_module).__name__}.{hook}()`. Try adding `dataloader_idx=0` to its signature.

What it means

Raised by _verify_dataloader_idx_requirement when multiple dataloaders were provided (is_expected True) but the matching step hook has no `dataloader_idx` parameter. With multiple loaders Lightning must tell the model which loader a batch came from; without the parameter the hook cannot receive it.

Source

Thrown at src/lightning/pytorch/loops/utilities.py:201

def _verify_dataloader_idx_requirement(
    hooks: tuple[str, ...], is_expected: bool, stage: RunningStage, pl_module: "pl.LightningModule"
) -> None:
    for hook in hooks:
        fx = getattr(pl_module, hook)
        # this validation only works if "dataloader_idx" is used, no other names such as "dl_idx"
        param_present = is_param_in_hook_signature(fx, "dataloader_idx")
        if not is_expected:
            if param_present:
                params = inspect.signature(fx).parameters
                if "dataloader_idx" in params and params["dataloader_idx"].default is inspect.Parameter.empty:
                    raise RuntimeError(
                        f"You provided only a single `{stage.dataloader_prefix}_dataloader`, but have included "
                        f"`dataloader_idx` in `{type(pl_module).__name__}.{hook}()`. Either remove the"
                        " argument or give it a default value i.e. `dataloader_idx=0`."
                    )
        elif not param_present:
            raise RuntimeError(
                f"You provided multiple `{stage.dataloader_prefix}_dataloader`, but no `dataloader_idx`"
                f" argument in `{type(pl_module).__name__}.{hook}()`. Try adding `dataloader_idx=0` to its"
                " signature."
            )

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Add the parameter with a default: `def training_step(self, batch, batch_idx, dataloader_idx=0)`
  2. Or reduce to a single dataloader / merge datasets with ConcatDataset if per-loader identity is unneeded

Example fix

# before
def training_step(self, batch, batch_idx):
    ...
trainer.fit(model, [dl1, dl2])

# after
def training_step(self, batch, batch_idx, dataloader_idx=0):
    ...
trainer.fit(model, [dl1, dl2])
Defensive patterns

Strategy: validation

Validate before calling

import inspect

multi = isinstance(dataloaders, (list, tuple)) and len(dataloaders) > 1
if multi:
    assert 'dataloader_idx' in inspect.signature(model.training_step).parameters

Type guard

def has_dataloader_idx(fn) -> bool:
    return 'dataloader_idx' in inspect.signature(fn).parameters

Prevention

When it happens

Trigger: `def training_step(self, batch, batch_idx):` with `trainer.fit(model, [dl1, dl2])` or a datamodule whose train_dataloader returns a list; same for validation_step/test_step/predict_step with multiple loaders.

Common situations: Adding a second val/train dataloader later without updating the LightningModule; using built-in multi-val-dataloader examples but copying a single-loader step signature.

Related errors


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