Lightning-AI/pytorch-lightning · error · RuntimeError
{self.__class__.__qualname__} is not attached to a `Trainer`
Error message
{self.__class__.__qualname__} is not attached to a `Trainer`. What it means
LightningModule.trainer raises RuntimeError when accessed before the Trainer has attached itself to the module (which happens inside trainer.fit/validate/test/predict). Any property/method that reads self.trainer outside Trainer-managed control flow will fail. A special case returns a shim when the module is attached to Fabric instead.
Source
Thrown at src/lightning/pytorch/core/module.py:218
if not self.trainer.lr_scheduler_configs:
return None
# ignore other keys "interval", "frequency", etc.
lr_schedulers: list[LRSchedulerPLType] = [config.scheduler for config in self.trainer.lr_scheduler_configs]
# single scheduler
if len(lr_schedulers) == 1:
return lr_schedulers[0]
# multiple schedulers
return lr_schedulers
@property
def trainer(self) -> "pl.Trainer":
if self._fabric is not None:
return _TrainerFabricShim(fabric=self._fabric) # type: ignore[return-value]
if not self._jit_is_scripting and self._trainer is None:
raise RuntimeError(f"{self.__class__.__qualname__} is not attached to a `Trainer`.")
return self._trainer # type: ignore[return-value]
@trainer.setter
def trainer(self, trainer: Optional["pl.Trainer"]) -> None:
for v in self.children():
if isinstance(v, LightningModule):
v.trainer = trainer
self._trainer = trainer
@property
def fabric(self) -> Optional["lf.Fabric"]:
return self._fabric
@fabric.setter
def fabric(self, fabric: Optional["lf.Fabric"]) -> None:
for v in self.children():
if isinstance(v, LightningModule):
v.fabric = fabricView on GitHub (pinned to 9fed5c27d2)
Solutions
- Move trainer-dependent logic into hooks that run under Trainer control (on_train_start, training_step, etc.)
- If testing, attach a Trainer first or mock the attribute
- Check `model._trainer is not None` (or use getattr guard) before accessing .trainer
- For Fabric workflows, attach the module via fabric.setup(model) so the shim is returned
Example fix
# before
class M(L.LightningModule):
def __init__(self):
super().__init__()
print(self.trainer.max_epochs) # RuntimeError
# after
class M(L.LightningModule):
def on_train_start(self):
print(self.trainer.max_epochs) # Trainer attached here Defensive patterns
Strategy: validation
Validate before calling
if model._trainer is None and model._fabric is None:
raise RuntimeError('attach model to a Trainer (trainer.fit) before accessing model.trainer') Type guard
def is_attached(module) -> bool:
return module._trainer is not None or module._fabric is not None Try / catch
try:
t = model.trainer
except RuntimeError as e:
if 'not attached' in str(e):
t = None # defer trainer-dependent logic to hooks
else:
raise Prevention
- Never read self.trainer in __init__ or plain functions
- Keep trainer-dependent logic in hooks like on_train_start/setup
When it happens
Trigger: Accessing self.trainer (directly or via self.log, self.device in some paths, checkpoint saving code) in __init__, in a plain script before trainer.fit, or in a datamodule hook not driven by the Trainer.
Common situations: Calling model.trainer in unit tests without a Trainer; using self.trainer.global_step in __init__; accessing trainer-dependent attributes when running the module standalone or with Fabric (where _fabric shim applies only if attached).
Related errors
- Device should be CUDA, got {device} instead.
- You requested to find {num_devices} devices but there are no
- You requested to find {num_devices} devices but this machine
- You requested to find {num_devices} devices but only {len(av
- Device should be MPS, got {device} instead.
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/390959db51aca3d9.
Report an issue: GitHub.