Lightning-AI/pytorch-lightning · error · TypeError

"`Trainer.test()` requires a `LightningModule` when it hasn'

Error message

"`Trainer.test()` requires a `LightningModule` when it hasn't been passed in a previous run"

What it means

trainer.test() was called with model=None on a Trainer that has no LightningModule reference from an earlier run. test() can only reuse a model if fit/validate/test/predict previously attached one; otherwise the model must be passed explicitly.

Source

Thrown at src/lightning/pytorch/trainer/trainer.py:817

            like :meth:`~lightning.pytorch.LightningModule.test_step` etc.
            The length of the list corresponds to the number of test dataloaders used.

        Raises:
            TypeError:
                If no ``model`` is passed and there was no ``LightningModule`` passed in the previous run.
                If ``model`` passed is not `LightningModule` or `torch._dynamo.OptimizedModule`.

            MisconfigurationException:
                If both ``dataloaders`` and ``datamodule`` are passed. Pass only one of these.

            RuntimeError:
                If a compiled ``model`` is passed and the strategy is not supported.

        """
        if model is None:
            # do we still have a reference from a previous call?
            if self.lightning_module is None:
                raise TypeError(
                    "`Trainer.test()` requires a `LightningModule` when it hasn't been passed in a previous run"
                )
        else:
            model = _maybe_unwrap_optimized(model)
            self.strategy._lightning_module = model
        _verify_strategy_supports_compile(self.lightning_module, self.strategy)
        self.state.fn = TrainerFn.TESTING
        self.state.status = TrainerStatus.RUNNING
        self.testing = True
        return call._call_and_handle_interrupt(
            self, self._test_impl, model, dataloaders, ckpt_path, verbose, datamodule, weights_only
        )

    def _test_impl(
        self,
        model: Optional["pl.LightningModule"] = None,
        dataloaders: Optional[Union[EVAL_DATALOADERS, LightningDataModule]] = None,
        ckpt_path: Optional[_PATH] = None,

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Pass the model: trainer.test(model, ckpt_path="best")
  2. Instantiate from checkpoint: model = LitModel.load_from_checkpoint(...) then trainer.test(model)
  3. Run trainer.fit(model) before trainer.test() on the same Trainer

Example fix

# before
trainer = Trainer()
trainer.test(ckpt_path="best.ckpt")
# after
model = LitModel.load_from_checkpoint("best.ckpt")
trainer.test(model)
Defensive patterns

Strategy: type-guard

Validate before calling

if trainer.lightning_module is None:
    model = LitModel.load_from_checkpoint("best.ckpt")
else:
    model = trainer.lightning_module
trainer.test(model, ckpt_path="best")

Type guard

def has_model(t) -> bool:
    return t.lightning_module is not None

Prevention

When it happens

Trigger: Fresh Trainer followed directly by trainer.test(); or constructing a new Trainer for evaluation without loading a model or checkpoint.

Common situations: Evaluation-only scripts that assume trainer.test(ckpt_path=...) alone suffices — a model instance is still required; the checkpoint only restores weights.

Related errors


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