Lightning-AI/pytorch-lightning · error · ValueError

`self.log({name}, {value})` was called, but nested dictionar

Error message

`self.log({name}, {value})` was called, but nested dictionaries cannot be logged

What it means

__check_not_nested rejects dictionaries passed to self.log whose values contain other dicts. This is a self-imposed simplicity restriction in the Fabric logging path: logged dicts must be flat maps of scalar/tensor values.

Source

Thrown at src/lightning/pytorch/core/module.py:653

    ) -> None:
        if logger is False:
            # Passing `logger=False` with Fabric does not make much sense because there is no other destination to
            # log to, but we support it in case the original code was written for Trainer use
            return

        if any(isinstance(v, dict) for v in dictionary.values()):
            raise ValueError(f"`self.log_dict({dictionary})` was called, but nested dictionaries cannot be logged")
        for name, value in dictionary.items():
            apply_to_collection(value, object, self.__check_allowed, name, value, wrong_dtype=(numbers.Number, Tensor))

        assert self._fabric is not None
        self._fabric.log_dict(metrics=dictionary)  # type: ignore[arg-type]

    @staticmethod
    def __check_not_nested(value: dict, name: str) -> None:
        # self-imposed restriction. for simplicity
        if any(isinstance(v, dict) for v in value.values()):
            raise ValueError(f"`self.log({name}, {value})` was called, but nested dictionaries cannot be logged")

    @staticmethod
    def __check_allowed(v: Any, name: str, value: Any) -> None:
        raise ValueError(f"`self.log({name}, {value})` was called, but `{type(v).__name__}` values cannot be logged")

    def __to_tensor(self, value: Union[Tensor, numbers.Number], name: str) -> Tensor:
        value = (
            value.clone().detach()
            if isinstance(value, Tensor)
            else torch.tensor(value, device=self.device, dtype=_get_default_dtype())
        )
        if not torch.numel(value) == 1:
            raise ValueError(
                f"`self.log({name}, {value})` was called, but the tensor must have a single element."
                f" You can try doing `self.log({name}, {value}.mean())`"
            )
        value = value.squeeze()
        return value

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Flatten nested keys with a separator before logging
  2. Use self.log_dict on the flattened dict

Example fix

# before
self.log('metrics', {'loss': {'total': l}})

# after
self.log('metrics/loss/total', l)
Defensive patterns

Strategy: type-guard

Validate before calling

if any(isinstance(v, dict) for v in value.values()):
    value = flatten(value)  # reuse a flatten helper
self.log(name, value)

Type guard

def is_not_nested(d) -> bool:
    return not any(isinstance(v, dict) for v in d.values())

Prevention

When it happens

Trigger: self.log(name, {'a': {'b': 1}}) or any dict value containing a dict when running under Fabric logging.

Common situations: Logging grouped/nested experiment configs or hierarchical metric trees directly instead of flattening keys.

Related errors


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