Lightning-AI/pytorch-lightning · error · MisconfigurationException

"`self.log(on_step=False, on_epoch=False)` is not useful."

Error message

"`self.log(on_step=False, on_epoch=False)` is not useful."

What it means

A _Metadata result record created via self.log must be aggregated either per step or per epoch (or both). __post_init__ rejects on_step=False, on_epoch=False because the logged value would be computed and then never surfaced anywhere — it is a no-op that hides bugs.

Source

Thrown at src/lightning/pytorch/trainer/connectors/logger_connector/result.py:123

@dataclass
class _Metadata:
    fx: str
    name: str
    prog_bar: bool = False
    logger: bool = True
    on_step: bool = False
    on_epoch: bool = True
    # https://github.com/pytorch/pytorch/issues/96197
    reduce_fx: Callable = torch.mean
    enable_graph: bool = False
    add_dataloader_idx: bool = True
    dataloader_idx: Optional[int] = None
    metric_attribute: Optional[str] = None
    _sync: Optional[_Sync] = None

    def __post_init__(self) -> None:
        if not self.on_step and not self.on_epoch:
            raise MisconfigurationException("`self.log(on_step=False, on_epoch=False)` is not useful.")
        self._parse_reduce_fx()

    def _parse_reduce_fx(self) -> None:
        error = (
            "Only `self.log(..., reduce_fx={min,max,mean,sum})` are supported."
            " If you need a custom reduction, please log a `torchmetrics.Metric` instance instead."
            f" Found: {self.reduce_fx}"
        )
        if isinstance(self.reduce_fx, str):
            reduce_fx = self.reduce_fx.lower()
            if reduce_fx == "avg":
                reduce_fx = "mean"
            if reduce_fx not in ("min", "max", "mean", "sum"):
                raise MisconfigurationException(error)
            self.reduce_fx = getattr(torch, reduce_fx)
        elif self.is_custom_reduction:
            raise MisconfigurationException(error)

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Enable at least one flag: on_step=True or on_epoch=True depending on the hook's allowed set
  2. If you only want the value on the progress bar, still keep an aggregation flag: self.log('x', x, prog_bar=True, on_step=True)
  3. If you do not want the metric at all, remove the self.log call

Example fix

# before
self.log('ratio', r, on_step=False, on_epoch=False)

# after
self.log('ratio', r, on_step=True, on_epoch=False)
Defensive patterns

Strategy: validation

Validate before calling

assert on_step or on_epoch, "self.log requires on_step=True or on_epoch=True"

Type guard

def is_useful_log(on_step: bool, on_epoch: bool) -> bool:
    return on_step or on_epoch

Prevention

When it happens

Trigger: self.log('x', x, on_step=False, on_epoch=False) — both aggregation flags explicitly disabled; the same error is raised for any Result/Metric construction path that funnels into _Metadata.__post_init__.

Common situations: Disabling on_epoch for a training metric and on_step for cleanup, accidentally ending with both False; copying log calls between hooks and flipping flags to silence the on_step/on_epoch validators until both end up False; programmatic logging loops that set flags from config.

Related errors


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