Lightning-AI/pytorch-lightning · error · MisconfigurationException

f"`check_val_every_n_epoch` should be an integer, found {che

Error message

f"`check_val_every_n_epoch` should be an integer, found {check_val_every_n_epoch!r}."

What it means

MisconfigurationException from DataConnector.on_trainer_init: check_val_every_n_epoch must be an int (or None). Floats such as 1.0 and strings are rejected with strict isinstance check, even if the value is numerically integral.

Source

Thrown at src/lightning/pytorch/trainer/connectors/data_connector.py:61

warning_cache = WarningCache()


class _DataConnector:
    def __init__(self, trainer: "pl.Trainer"):
        self.trainer = trainer
        self._datahook_selector: Optional[_DataHookSelector] = None

    def on_trainer_init(
        self,
        val_check_interval: Optional[Union[int, float, str, timedelta, dict]],
        reload_dataloaders_every_n_epochs: int,
        check_val_every_n_epoch: Optional[int],
    ) -> None:
        self.trainer.datamodule = None

        if check_val_every_n_epoch is not None and not isinstance(check_val_every_n_epoch, int):
            raise MisconfigurationException(
                f"`check_val_every_n_epoch` should be an integer, found {check_val_every_n_epoch!r}."
            )

        if check_val_every_n_epoch is None and isinstance(val_check_interval, float):
            raise MisconfigurationException(
                "`val_check_interval` should be an integer or a time-based duration (str 'DD:HH:MM:SS', "
                "datetime.timedelta, or dict kwargs for timedelta) when `check_val_every_n_epoch=None`."
            )

        self.trainer.check_val_every_n_epoch = check_val_every_n_epoch

        if not isinstance(reload_dataloaders_every_n_epochs, int) or (reload_dataloaders_every_n_epochs < 0):
            raise MisconfigurationException(
                f"`reload_dataloaders_every_n_epochs` should be an int >= 0, got {reload_dataloaders_every_n_epochs}."
            )

        self.trainer.reload_dataloaders_every_n_epochs = reload_dataloaders_every_n_epochs

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Convert to int before constructing: Trainer(check_val_every_n_epoch=int(value))
  2. Set the value to None to validate every epoch (default 1.0-equivalent behavior uses interval checks)
  3. Fix the config file/YAML so the value is an unquoted integer

Example fix

# before
trainer = Trainer(check_val_every_n_epoch=1.0)
# after
trainer = Trainer(check_val_every_n_epoch=1)
Defensive patterns

Strategy: type-guard

Validate before calling

if check_val_every_n_epoch is not None:
    check_val_every_n_epoch = int(check_val_every_n_epoch)
trainer = Trainer(check_val_every_n_epoch=check_val_every_n_epoch)

Type guard

def is_valid_check_val_every_n_epoch(v) -> bool:
    return v is None or (isinstance(v, int) and not isinstance(v, bool))

Prevention

When it happens

Trigger: Trainer(check_val_every_n_epoch=1.0), or passing a config-parsed value (YAML/JSON/argparse) that arrives as float/str; np.int64 also fails the plain isinstance int check in some numpy versions.

Common situations: Hyperparameter sweeps (optuna/wandb) supplying floats; YAML configs where the value is quoted; numpy scalars from computed schedules.

Related errors


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