{"record":{"id":"1362aea7b577f63c","repo":"Lightning-AI/pytorch-lightning","slug":"max-steps-must-be-a-non-negative-integer-or-1","errorCode":null,"errorMessage":"`max_steps` must be a non-negative integer or -1 (infinite steps). You passed in {max_steps}.","messagePattern":"`max_steps` must be a non-negative integer or -1 \\(infinite steps\\)\\. You passed in (.+?)\\.","errorType":"exception","errorClass":"MisconfigurationException","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/loops/training_epoch_loop.py","lineNumber":76,"sourceCode":"    The validation is carried out by yet another loop,\n    :class:`~lightning.pytorch.loops._EvaluationLoop`.\n\n    In the ``run()`` method, the training epoch loop could in theory simply call the\n    ``LightningModule.training_step`` already and perform the optimization.\n    However, Lightning has built-in support for automatic optimization with multiple optimizers.\n    For this reason there are actually two more loops nested under\n    :class:`~lightning.pytorch.loops._TrainingEpochLoop`.\n\n    Args:\n        min_steps: The minimum number of steps (batches) to process\n        max_steps: The maximum number of steps (batches) to process\n\n    \"\"\"\n\n    def __init__(self, trainer: \"pl.Trainer\", min_steps: Optional[int] = None, max_steps: int = -1) -> None:\n        super().__init__(trainer)\n        if max_steps < -1:\n            raise MisconfigurationException(\n                f\"`max_steps` must be a non-negative integer or -1 (infinite steps). You passed in {max_steps}.\"\n            )\n        self.min_steps = min_steps\n        self.max_steps = max_steps\n\n        self.batch_progress = _BatchProgress()\n        self.scheduler_progress = _SchedulerProgress()\n\n        self.automatic_optimization = _AutomaticOptimization(trainer)\n        self.manual_optimization = _ManualOptimization(trainer)\n\n        self.val_loop = loops._EvaluationLoop(\n            trainer, TrainerFn.FITTING, RunningStage.VALIDATING, verbose=False, inference_mode=False\n        )\n\n        self._results = _ResultCollection(training=True)\n        self._warning_cache = WarningCache()\n        self._batches_that_stepped: int = 0","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/loops/training_epoch_loop.py#L58-L94","documentation":"Raised by _TrainingEpochLoop.__init__ when the max_steps argument is an int strictly less than -1. -1 means 'unlimited steps' (the default) and 0 is allowed, so anything below -1 is treated as an invalid hyperparameter.","triggerScenarios":"Setting `Trainer(max_steps=-2)`; deriving max_steps from arithmetic like `max_steps=remaining_steps - overhang` that goes below -1; config files with negative step budgets.","commonSituations":"Resume-from-checkpoint logic computing remaining steps incorrectly; CLI misparsing; copying max_epochs-style -1 sentinel conventions while also subtracting values.","solutions":["Set max_steps to a non-negative int or -1 (infinite)","Clamp computed values: `max_steps = max(max_steps, -1)`","Log/inspect the computed max_steps before constructing the Trainer"],"exampleFix":"# before\ntrainer = pl.Trainer(max_steps=steps_left - 10)  # can be -2\n\n# after\ntrainer = pl.Trainer(max_steps=max(steps_left - 10, -1))","handlingStrategy":"validation","validationCode":"max_steps = max(cfg['max_steps'], -1) if isinstance(cfg['max_steps'], int) else -1\ntrainer = pl.Trainer(max_steps=max_steps)","typeGuard":"def valid_max_steps(v) -> bool:\n    return isinstance(v, int) and v >= -1","tryCatchPattern":null,"preventionTips":["Validate computed step budgets against the -1 sentinel before Trainer construction","Log effective Trainer hyperparameters when resuming from checkpoints"],"tags":["pytorch-lightning","trainer","max-steps","validation"],"backgroundTag":"invalid-training-hyperparameter","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}