Lightning-AI/pytorch-lightning · error · ValueError

`self.log({name}, {value})` was called, but the tensor must

Error message

`self.log({name}, {value})` was called, but the tensor must have a single element. You can try doing `self.log({name}, {value}.mean())`

What it means

__to_tensor requires every logged tensor to contain exactly one element (a scalar) so it can be aggregated. Tensors with more than one element (or zero) raise ValueError; the message suggests reducing via .mean().

Source

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

    @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

    def all_gather(
        self, data: Union[Tensor, dict, list, tuple], group: Optional[Any] = None, sync_grads: bool = False
    ) -> Union[Tensor, dict, list, tuple]:
        r"""Gather tensors or collections of tensors from multiple processes.

        This method needs to be called on all processes and the tensors need to have the same shape across all
        processes, otherwise your program will stall forever.

        Args:
            data: int, float, tensor of shape (batch, ...), or a (possibly nested) collection thereof.
            group: the process group to gather results from. Defaults to all processes (world)
            sync_grads: flag that allows users to synchronize gradients for the all_gather operation

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Reduce to a scalar: self.log('loss', loss.mean()) (or .sum()/.max() as appropriate)
  2. Ensure losses computed in training_step are already reduced to one value
  3. Log per-class values under separate scalar keys instead of one vector

Example fix

# before
self.log('loss', losses)  # shape [B]

# after
self.log('loss', losses.mean())
Defensive patterns

Strategy: validation

Validate before calling

import torch
def scalarize(t):
    return t.mean() if isinstance(t, torch.Tensor) and t.numel() != 1 else t
self.log(name, scalarize(value))

Type guard

def is_scalar_tensor(v) -> bool:
    import torch
    return not isinstance(v, torch.Tensor) or v.numel() == 1

Prevention

When it happens

Trigger: self.log('loss', per_sample_losses) where the tensor has shape [batch_size]; logging a vector, image tensor, or empty tensor.

Common situations: User logs unreduced loss over the batch, logs predictions array, or logs a tensor that got squeezed to empty.

Related errors


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