Lightning-AI/pytorch-lightning · error · MisconfigurationException

`mode` can be {', '.join(self.mode_dict.keys())}, got {self.

Error message

`mode` can be {', '.join(self.mode_dict.keys())}, got {self.mode}

What it means

EarlyStopping validates its `mode` argument against a fixed set (`min`, `max`) stored in `self.mode_dict`. Any other string raises a MisconfigurationException at callback construction time. The mode determines whether the monitored metric is minimized or maximized.

Source

Thrown at src/lightning/pytorch/callbacks/early_stopping.py:146

        super().__init__()
        self.monitor = monitor
        self.min_delta = min_delta
        self.patience = patience
        self.verbose = verbose
        self.mode = mode
        self.strict = strict
        self.check_finite = check_finite
        self.stopping_threshold = stopping_threshold
        self.divergence_threshold = divergence_threshold
        self.wait_count = 0
        self.stopped_epoch = 0
        self.stopping_reason = EarlyStoppingReason.NOT_STOPPED
        self.stopping_reason_message: Optional[str] = None
        self._check_on_train_epoch_end = check_on_train_epoch_end
        self.log_rank_zero_only = log_rank_zero_only

        if self.mode not in self.mode_dict:
            raise MisconfigurationException(f"`mode` can be {', '.join(self.mode_dict.keys())}, got {self.mode}")

        self.min_delta *= 1 if self.monitor_op == torch.gt else -1
        torch_inf = torch.tensor(torch.inf)
        self.best_score = torch_inf if self.monitor_op == torch.lt else -torch_inf

    @property
    @override
    def state_key(self) -> str:
        return self._generate_state_key(monitor=self.monitor, mode=self.mode)

    @override
    def setup(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule", stage: str) -> None:
        if self._check_on_train_epoch_end is None:
            # if the user runs validation multiple times per training epoch or multiple training epochs without
            # validation, then we run after validation instead of on train epoch end
            self._check_on_train_epoch_end = trainer.val_check_interval == 1.0 and trainer.check_val_every_n_epoch == 1

    def _validate_condition_metric(self, logs: dict[str, Tensor]) -> bool:

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Set `mode='min'` for losses or `mode='max'` for metrics like accuracy — these are the only accepted values
  2. Check for casing/whitespace: 'Min', ' min ' are rejected
  3. If mode comes from a config file, validate it before constructing the callback

Example fix

// before
EarlyStopping(monitor='val_loss', mode='minimum')
// after
EarlyStopping(monitor='val_loss', mode='min')
Defensive patterns

Strategy: validation

Validate before calling

from lightning.pytorch.callbacks.early_stopping import EarlyStopping
mode = 'min'  # from config
assert mode in ('min', 'max'), f"mode must be min/max, got {mode!r}"

Type guard

def is_valid_es_mode(mode: str) -> bool:
    return isinstance(mode, str) and mode in ('min', 'max')

Prevention

When it happens

Trigger: Instantiating `EarlyStopping(monitor='val_loss', mode='ascending')` or passing a typo like `mode='Min'` (case-sensitive) or `mode='minimum'`. The check runs in `__init__`, so it fails immediately when the callback is created, before any training.

Common situations: Typos or case mistakes in `mode`; copying config from another library that uses different mode names (e.g. 'auto', 'higher'); passing mode programmatically from a config value that is misspelled.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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