Lightning-AI/pytorch-lightning · error · MisconfigurationException

Automatic gradient clipping is not supported for manual opti

Error message

Automatic gradient clipping is not supported for manual optimization. Remove `Trainer(gradient_clip_val={trainer.gradient_clip_val})` or switch to automatic optimization.

What it means

With `automatic_optimization=False`, Lightning does not wrap the training step in its own backward/clip routine, so Trainer-level `gradient_clip_val` has no effect and is rejected at configuration validation time. The guard fires when gradient_clip_val is set to a positive value on a manually-optimized model.

Source

Thrown at src/lightning/pytorch/trainer/configuration_validator.py:123

            trainer_method = "validate" if stage == "val" else stage
            raise MisconfigurationException(f"No `{step_name}()` method defined to run `Trainer.{trainer_method}`.")

        # check legacy hooks are not present
        epoch_end_name = "validation_epoch_end" if stage == "val" else "test_epoch_end"
        if callable(getattr(model, epoch_end_name, None)):
            raise NotImplementedError(
                f"Support for `{epoch_end_name}` has been removed in v2.0.0. `{type(model).__name__}` implements this"
                f" method. You can use the `on_{epoch_end_name}` hook instead. To access outputs, save them in-memory"
                " as instance attributes."
                " You can find migration examples in https://github.com/Lightning-AI/pytorch-lightning/pull/16520."
            )


def __verify_manual_optimization_support(trainer: "pl.Trainer", model: "pl.LightningModule") -> None:
    if model.automatic_optimization:
        return
    if trainer.gradient_clip_val is not None and trainer.gradient_clip_val > 0:
        raise MisconfigurationException(
            "Automatic gradient clipping is not supported for manual optimization."
            f" Remove `Trainer(gradient_clip_val={trainer.gradient_clip_val})`"
            " or switch to automatic optimization."
        )
    if trainer.accumulate_grad_batches != 1:
        raise MisconfigurationException(
            "Automatic gradient accumulation is not supported for manual optimization."
            f" Remove `Trainer(accumulate_grad_batches={trainer.accumulate_grad_batches})`"
            " or switch to automatic optimization."
        )


def __warn_dataloader_iter_limitations(model: "pl.LightningModule") -> None:
    """Check if `dataloader_iter is enabled`."""
    if any(
        is_param_in_hook_signature(step_fn, "dataloader_iter", explicit=True)
        for step_fn in (model.training_step, model.validation_step, model.predict_step, model.test_step)
        if step_fn is not None

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Remove `gradient_clip_val` from the Trainer if you rely on manual optimization.
  2. Or clip gradients yourself inside `training_step` via `torch.nn.utils.clip_grad_norm_(self.parameters(), val)` after `optimizer.backward()`/`closure` calls.
  3. Or switch back to automatic optimization (`automatic_optimization = True`) so Lightning applies clipping.

Example fix

# before
model.automatic_optimization = False
trainer = Trainer(gradient_clip_val=0.5)
# after (clip manually)
model.automatic_optimization = False
trainer = Trainer()
# inside training_step:
#   self.manual_backward(loss)
#   torch.nn.utils.clip_grad_norm_(self.parameters(), 0.5)
#   opt.step(); opt.zero_grad()
Defensive patterns

Strategy: validation

Validate before calling

def check_trainer_config(model, trainer_kwargs):
    if getattr(model, 'automatic_optimization', True) is False:
        if (trainer_kwargs.get('gradient_clip_val') or 0) > 0:
            raise ValueError('gradient_clip_val unsupported with manual optimization; clip manually')
    return trainer_kwargs

Type guard

def is_auto_opt(model: "pl.LightningModule") -> bool:
    return bool(getattr(model, 'automatic_optimization', True))

Try / catch

try:
    trainer = Trainer(gradient_clip_val=cfg.clip)
    trainer.fit(model)
except MisconfigurationException as e:
    if 'gradient clipping is not supported for manual' in str(e).lower():
        trainer = Trainer()  # clip inside training_step instead
        trainer.fit(model)
    else:
        raise

Prevention

When it happens

Trigger: Setting `LightningModule.automatic_optimization = False` together with `Trainer(gradient_clip_val=5.0)` (or any positive value, including via CLI defaults).

Common situations: GAN training, reinforcement-learning loops, or meta-learning code using manual optimization while the Trainer config was copied from a standard classification script; enabling gradient clipping 'for safety' on a manual-optimization model.

Related errors


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