{"record":{"id":"5f8b56d8bf67f6eb","repo":"unslothai/unsloth","slug":"only-one-lora-variant-may-be-enabled-at-a-time-go","errorCode":null,"errorMessage":"Only one LoRA variant may be enabled at a time; got {active}. use_rslora, use_loftq, and use_dora are mutually exclusive.","messagePattern":"Only one LoRA variant may be enabled at a time; got (.+?)\\. use_rslora, use_loftq, and use_dora are mutually exclusive\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/models/training.py","lineNumber":621,"sourceCode":"            raise ValueError(\"Either num_epochs or max_steps must be > 0; both cannot be 0.\")\n        return self\n\n    @model_validator(mode = \"after\")\n    def _validate_lora_variant_flags(self) -> \"TrainingStartRequest\":\n        # The frontend only ever sends one of these and never under Full Finetuning, but a direct\n        # API/YAML/CLI caller can bypass that. Nothing downstream breaks, but reject early for a\n        # clear error instead of a silently-ignored flag.\n        active = [\n            name\n            for name, enabled in (\n                (\"use_rslora\", self.use_rslora),\n                (\"use_loftq\", self.use_loftq),\n                (\"use_dora\", self.use_dora),\n            )\n            if enabled\n        ]\n        if len(active) > 1:\n            raise ValueError(\n                f\"Only one LoRA variant may be enabled at a time; got {active}. \"\n                \"use_rslora, use_loftq, and use_dora are mutually exclusive.\"\n            )\n        # getattr, not self.training_type: model_construct() (used by single-field tests) leaves\n        # required fields unset, and this mode=\"after\" validator still runs on that partial instance.\n        if getattr(self, \"training_type\", None) == \"Full Finetuning\" and active:\n            raise ValueError(\n                f\"{active[0]} requires an adapter method (LoRA/QLoRA or \"\n                \"Continued Pretraining); it has no effect under Full Finetuning.\"\n            )\n        return self\n\n\nclass TrainingJobResponse(BaseModel):\n    \"\"\"Immediate response when training is initiated\"\"\"\n\n    job_id: str = Field(..., description = \"Unique training job identifier\")\n    status: Literal[\"pending\", \"queued\", \"error\"] = Field(..., description = \"Initial job status\")","sourceCodeStart":603,"sourceCodeEnd":639,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/models/training.py#L603-L639","documentation":"Pydantic model validator _validate_lora_variant_flags ensuring the LoRA variant flags use_rslora, use_loftq, and use_dora are mutually exclusive. The frontend only ever sends one, but a direct API/YAML/CLI caller can set several at once; nothing downstream breaks, so the model rejects early with a clear error instead of silently ignoring the extra flags.","triggerScenarios":"POSTing a TrainingStartRequest with any two of use_rslora/use_loftq/use_dora set to true simultaneously (e.g. use_rslora=True and use_dora=True). Fires at validation time on the combined 'active' list.","commonSituations":"Hand-written YAML recipes that layer flags from multiple examples; copy-pasting config snippets from different tutorials; scripts that merge defaults from one adapter type with overrides from another.","solutions":["Enable exactly one variant flag (or none) — decide whether you want rank-stabilized (use_rslora), LoftQ init (use_loftq), or DoRA (use_dora) and remove the others.","Check your config merge logic: a base config with use_rslora=true plus an override adding use_dora=true produces this error.","If unsure, disable all variant flags to use plain LoRA/QLoRA."],"exampleFix":"# before\nreq = TrainingStartRequest(use_rslora=True, use_dora=True, ...)\n\n# after\nreq = TrainingStartRequest(use_rslora=True, ...)","handlingStrategy":"validation","validationCode":"LORA_VARIANT_FLAGS = (\"use_rslora\", \"use_loftq\", \"use_dora\")\n\ndef active_variants(payload: dict) -> list[str]:\n    return [f for f in LORA_VARIANT_FLAGS if payload.get(f)]\n\ndef variants_valid(payload: dict) -> bool:\n    return len(active_variants(payload)) <= 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Expose variant flags as a single-choice enum (adapter_variant: none|rslora|loftq|dora) in your own UI/config layer instead of three booleans.","Lint merged YAML configs for multiple variant flags before submission."],"tags":["pydantic","lora","fine-tuning","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}