unslothai/unsloth · error · ValueError
Only one LoRA variant may be enabled at a time; got {active}
Error message
Only one LoRA variant may be enabled at a time; got {active}. use_rslora, use_loftq, and use_dora are mutually exclusive. What it means
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.
Source
Thrown at studio/backend/models/training.py:621
raise ValueError("Either num_epochs or max_steps must be > 0; both cannot be 0.")
return self
@model_validator(mode = "after")
def _validate_lora_variant_flags(self) -> "TrainingStartRequest":
# The frontend only ever sends one of these and never under Full Finetuning, but a direct
# API/YAML/CLI caller can bypass that. Nothing downstream breaks, but reject early for a
# clear error instead of a silently-ignored flag.
active = [
name
for name, enabled in (
("use_rslora", self.use_rslora),
("use_loftq", self.use_loftq),
("use_dora", self.use_dora),
)
if enabled
]
if len(active) > 1:
raise ValueError(
f"Only one LoRA variant may be enabled at a time; got {active}. "
"use_rslora, use_loftq, and use_dora are mutually exclusive."
)
# getattr, not self.training_type: model_construct() (used by single-field tests) leaves
# required fields unset, and this mode="after" validator still runs on that partial instance.
if getattr(self, "training_type", None) == "Full Finetuning" and active:
raise ValueError(
f"{active[0]} requires an adapter method (LoRA/QLoRA or "
"Continued Pretraining); it has no effect under Full Finetuning."
)
return self
class TrainingJobResponse(BaseModel):
"""Immediate response when training is initiated"""
job_id: str = Field(..., description = "Unique training job identifier")
status: Literal["pending", "queued", "error"] = Field(..., description = "Initial job status")View on GitHub (pinned to 203007d190)
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.
Example fix
# before req = TrainingStartRequest(use_rslora=True, use_dora=True, ...) # after req = TrainingStartRequest(use_rslora=True, ...)
Defensive patterns
Strategy: validation
Validate before calling
LORA_VARIANT_FLAGS = ("use_rslora", "use_loftq", "use_dora")
def active_variants(payload: dict) -> list[str]:
return [f for f in LORA_VARIANT_FLAGS if payload.get(f)]
def variants_valid(payload: dict) -> bool:
return len(active_variants(payload)) <= 1 Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {active[0]} requires an adapter method (LoRA/QLoRA or Contin
- duplicate LoRA id '{spec.id}'; list each adapter at most onc
- GGUF LoRA adapters are not supported on the diffusers engine
- LoRA is not supported for {state.family.name} on the native
- gradient_accumulation_steps must be >= 1
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/5f8b56d8bf67f6eb.
Report an issue: GitHub.