Lightning-AI/pytorch-lightning · error · TypeError

`devices` selected with `CPUAccelerator` should be an int >

Error message

`devices` selected with `CPUAccelerator` should be an int > 0.

What it means

When a logged metric has sync_dist=True (or is otherwise a torchmetrics Metric), Lightning calls the metric's .compute() and expects a single torch.Tensor back. This ValueError is thrown in _get_cache when the computed cache exists but is not a Tensor (e.g. a tuple, dict, list, or number).

Source

Thrown at src/lightning/fabric/accelerators/cpu.py:99

    """Parses the cpu_cores given in the format as accepted by the ``devices`` argument in the
    :class:`~lightning.pytorch.trainer.trainer.Trainer`.

    Args:
        cpu_cores: An int > 0 or a string that can be converted to an int > 0.

    Returns:
        An int representing the number of processes

    Raises:
        MisconfigurationException:
            If cpu_cores is not an int > 0

    """
    if isinstance(cpu_cores, str) and cpu_cores.strip().isdigit():
        cpu_cores = int(cpu_cores)

    if not isinstance(cpu_cores, int) or cpu_cores <= 0:
        raise TypeError("`devices` selected with `CPUAccelerator` should be an int > 0.")

    return cpu_cores

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Make the custom Metric.compute() return a single torch.Tensor (stack/cat or index into the collection)
  2. Split multi-output metrics into separate Metric instances, one per scalar, each logged with its own name
  3. Return a scalar tensor: e.g. return loss.item() -> return torch.tensor(loss) is wrong; return loss if loss is already a tensor

Example fix

# before
class MyMetric(Metric):
    def compute(self):
        return self.tp, self.fp  # tuple -> raises

# after
class MyMetric(Metric):
    def compute(self):
        return torch.stack([self.tp.float(), self.fp.float()])
# or two separate metrics logged under distinct names
Defensive patterns

Strategy: validation

Validate before calling

import torch
from torchmetrics import Metric

def compute_is_tensor(metric: Metric) -> bool:
    out = metric.compute()
    return isinstance(out, torch.Tensor)

Type guard

from torch import Tensor
from torchmetrics import Metric

def metric_returns_tensor(m: Metric) -> bool:
    try:
        return isinstance(m.compute(), Tensor)
    except Exception:
        return False

Try / catch

try:
    value = trainer.callback_metrics["my_metric"]
except (ValueError, KeyError) as e:
    # metric.compute() did not return a tensor
    logger.warning("skipping metric: %s", e)
    value = None

Prevention

When it happens

Trigger: Logging a torchmetrics Metric whose compute() returns a tuple (like returning (loss, acc)) or a dict; logging a custom Metric subclass whose compute() returns a Python float or a collection; metrics with enable_graph/sync_dist paths that read result_metric._computed in _get_cache (used by metrics(), tests like test_metric_result_computed_check).

Common situations: Wrapping a model that returns multiple outputs into one Metric.compute(); using ClassificationTask-style metrics returning dicts; upgrading torchmetrics where compute() signatures changed; writing custom metrics without returning a tensor.

Related errors


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