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

  1. 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.
  2. Check your config merge logic: a base config with use_rslora=true plus an override adding use_dora=true produces this error.
  3. 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

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


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/5f8b56d8bf67f6eb. Report an issue: GitHub.