Lightning-AI/pytorch-lightning · error · MisconfigurationException

f"You can't `self.log()` inside `{fx_name}`. HINT: You can s

Error message

f"You can't `self.log()` inside `{fx_name}`. HINT: You can still log directly to the logger by using" " `self.logger.experiment`."

What it means

_FxValidator.functions maps each hook to either a config dict (logging allowed with constraints) or None (logging forbidden). When self.log() is called inside a hook whose entry is None — typically hooks that run outside the metric-collection machinery like on_train_start or configure_optimizers — this MisconfigurationException is raised.

Source

Thrown at src/lightning/pytorch/trainer/connectors/logger_connector/fx_validator.py:161

        "configure_callbacks": None,
        "on_validation_model_zero_grad": None,
        "on_validation_model_eval": None,
        "on_test_model_eval": None,
        "on_validation_model_train": None,
        "on_test_model_train": None,
    }

    @classmethod
    def check_logging(cls, fx_name: str) -> None:
        """Check if the given hook is allowed to log."""
        if fx_name not in cls.functions:
            raise RuntimeError(
                f"Logging inside `{fx_name}` is not implemented."
                " Please, open an issue in `https://github.com/Lightning-AI/pytorch-lightning/issues`."
            )

        if cls.functions[fx_name] is None:
            raise MisconfigurationException(
                f"You can't `self.log()` inside `{fx_name}`. HINT: You can still log directly to the logger by using"
                " `self.logger.experiment`."
            )

    @classmethod
    def get_default_logging_levels(
        cls, fx_name: str, on_step: Optional[bool], on_epoch: Optional[bool]
    ) -> tuple[bool, bool]:
        """Return default logging levels for given hook."""
        fx_config = cls.functions[fx_name]
        assert fx_config is not None
        on_step = fx_config["default_on_step"] if on_step is None else on_step
        on_epoch = fx_config["default_on_epoch"] if on_epoch is None else on_epoch
        return on_step, on_epoch

    @classmethod
    def check_logging_levels(cls, fx_name: str, on_step: bool, on_epoch: bool) -> None:
        """Check if the logging levels are allowed in the given hook."""

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Log directly to the logger backend instead: self.logger.experiment.add_scalar('foo', x) (TensorBoard) or self.logger.experiment.log_metric(...) (MLflow/W&B)
  2. Move the logging into an allowed hook such as training_step or validation_step (optionally accumulated)
  3. For scalars like LR, prefer self.log('lr', ..., on_step=True) inside training_step rather than on_train_start

Example fix

# before
def on_train_start(self, trainer, pl_module):
    self.log('epoch', 0)

# after
def on_train_start(self, trainer, pl_module):
    trainer.logger.experiment.add_scalar('epoch', 0, 0)
Defensive patterns

Strategy: fallback

Validate before calling

from lightning.pytorch.trainer.connectors.logger_connector.fx_validator import _FxValidator

if _FxValidator.functions.get(hook_name) is None:
    use_logger_experiment()  # do not call self.log here

Type guard

def can_self_log(hook_name: str) -> bool:
    from lightning.pytorch.trainer.connectors.logger_connector import fx_validator
    cfg = fx_validator._FxValidator.functions.get(hook_name)
    return cfg is not None

Try / catch

try:
    self.log(name, value)
except MisconfigurationException:
    self.logger.experiment.add_scalar(name, value)

Prevention

When it happens

Trigger: Calling self.log('foo', x) inside hooks like on_train_start, on_train_epoch_start, setup, configure_optimizers, or on_test_end, whose registry value is None; also custom hooks invoked with those fx_names.

Common situations: Logging an epoch-start summary or learning-rate diagnostics in on_train_start via self.log; migrating code that used experiment.log_metric before; logging in teardown for final aggregates.

Related errors


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