{"record":{"id":"3d81ca353c9d812a","repo":"Lightning-AI/pytorch-lightning","slug":"automatic-gradient-clipping-is-not-supported-for-m","errorCode":null,"errorMessage":"Automatic gradient clipping is not supported for manual optimization. Remove `Trainer(gradient_clip_val={trainer.gradient_clip_val})` or switch to automatic optimization.","messagePattern":"Automatic gradient clipping is not supported for manual optimization\\. Remove `Trainer\\(gradient_clip_val=(.+?)\\)` or switch to automatic optimization\\.","errorType":"validation","errorClass":"MisconfigurationException","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/trainer/configuration_validator.py","lineNumber":123,"sourceCode":"            trainer_method = \"validate\" if stage == \"val\" else stage\n            raise MisconfigurationException(f\"No `{step_name}()` method defined to run `Trainer.{trainer_method}`.\")\n\n        # check legacy hooks are not present\n        epoch_end_name = \"validation_epoch_end\" if stage == \"val\" else \"test_epoch_end\"\n        if callable(getattr(model, epoch_end_name, None)):\n            raise NotImplementedError(\n                f\"Support for `{epoch_end_name}` has been removed in v2.0.0. `{type(model).__name__}` implements this\"\n                f\" method. You can use the `on_{epoch_end_name}` hook instead. To access outputs, save them in-memory\"\n                \" as instance attributes.\"\n                \" You can find migration examples in https://github.com/Lightning-AI/pytorch-lightning/pull/16520.\"\n            )\n\n\ndef __verify_manual_optimization_support(trainer: \"pl.Trainer\", model: \"pl.LightningModule\") -> None:\n    if model.automatic_optimization:\n        return\n    if trainer.gradient_clip_val is not None and trainer.gradient_clip_val > 0:\n        raise MisconfigurationException(\n            \"Automatic gradient clipping is not supported for manual optimization.\"\n            f\" Remove `Trainer(gradient_clip_val={trainer.gradient_clip_val})`\"\n            \" or switch to automatic optimization.\"\n        )\n    if trainer.accumulate_grad_batches != 1:\n        raise MisconfigurationException(\n            \"Automatic gradient accumulation is not supported for manual optimization.\"\n            f\" Remove `Trainer(accumulate_grad_batches={trainer.accumulate_grad_batches})`\"\n            \" or switch to automatic optimization.\"\n        )\n\n\ndef __warn_dataloader_iter_limitations(model: \"pl.LightningModule\") -> None:\n    \"\"\"Check if `dataloader_iter is enabled`.\"\"\"\n    if any(\n        is_param_in_hook_signature(step_fn, \"dataloader_iter\", explicit=True)\n        for step_fn in (model.training_step, model.validation_step, model.predict_step, model.test_step)\n        if step_fn is not None","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/trainer/configuration_validator.py#L105-L141","documentation":"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.","triggerScenarios":"Setting `LightningModule.automatic_optimization = False` together with `Trainer(gradient_clip_val=5.0)` (or any positive value, including via CLI defaults).","commonSituations":"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.","solutions":["Remove `gradient_clip_val` from the Trainer if you rely on manual optimization.","Or clip gradients yourself inside `training_step` via `torch.nn.utils.clip_grad_norm_(self.parameters(), val)` after `optimizer.backward()`/`closure` calls.","Or switch back to automatic optimization (`automatic_optimization = True`) so Lightning applies clipping."],"exampleFix":"# before\nmodel.automatic_optimization = False\ntrainer = Trainer(gradient_clip_val=0.5)\n# after (clip manually)\nmodel.automatic_optimization = False\ntrainer = Trainer()\n# inside training_step:\n#   self.manual_backward(loss)\n#   torch.nn.utils.clip_grad_norm_(self.parameters(), 0.5)\n#   opt.step(); opt.zero_grad()","handlingStrategy":"validation","validationCode":"def check_trainer_config(model, trainer_kwargs):\n    if getattr(model, 'automatic_optimization', True) is False:\n        if (trainer_kwargs.get('gradient_clip_val') or 0) > 0:\n            raise ValueError('gradient_clip_val unsupported with manual optimization; clip manually')\n    return trainer_kwargs","typeGuard":"def is_auto_opt(model: \"pl.LightningModule\") -> bool:\n    return bool(getattr(model, 'automatic_optimization', True))","tryCatchPattern":"try:\n    trainer = Trainer(gradient_clip_val=cfg.clip)\n    trainer.fit(model)\nexcept MisconfigurationException as e:\n    if 'gradient clipping is not supported for manual' in str(e).lower():\n        trainer = Trainer()  # clip inside training_step instead\n        trainer.fit(model)\n    else:\n        raise","preventionTips":["Keep Trainer kwargs in per-model config presets, not one global dict.","Centralize clip logic: either Trainer-level for automatic opt, or explicit torch.nn.utils.clip_grad_norm_ for manual."],"tags":["pytorch-lightning","manual-optimization","gradient-clipping","configuration"],"backgroundTag":"incompatible-trainer-options","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}