unslothai/unsloth · error · ValueError

No DiT trainer for family {cfg.resolved_family!r}

Error message

No DiT trainer for family {cfg.resolved_family!r}

What it means

Raised at the top of the DiT LoRA trainer when the normalized config's resolved_family has no entry in _SPECS. resolved_family is what normalization computes from the base model, so this means the run targets a family the trainer build knows nothing about. It fails before any heavy imports, so it is purely a config/version mismatch signal.

Source

Thrown at studio/backend/core/training/diffusion_dit_trainer.py:1838

        return False


def run_dit_lora_training(
    config: DiffusionLoraConfig,
    *,
    on_event: Optional[EventCb] = None,
    should_stop: Optional[StopCb] = None,
) -> str:
    """Train a flow-matching DiT LoRA (FLUX.1 / FLUX.2 / Qwen-Image / Z-Image / Krea 2 / LTX-2) and export it.

    Resumable: ``cfg.resume_from_checkpoint`` restores the adapter, optimizer moments, LR
    position, EMA shadow, sampler cycle and RNG streams from a ``checkpoint-<N>`` bundle,
    and the loop runs steps N+1..train_steps (the TARGET TOTAL). A stop-and-save and every
    ``cfg.save_steps`` interval write such a bundle."""
    cfg = config.normalized()
    spec = _SPECS.get(cfg.resolved_family)
    if spec is None:
        raise ValueError(f"No DiT trainer for family {cfg.resolved_family!r}")

    # DiT families train in bf16, so an explicit fp16 request is refused, not silently upgraded. Validated before the heavy imports so a host without diffusers still sees the real error.
    if cfg.mixed_precision == "fp16" and spec.force_bf16:
        raise ValueError(
            f"{spec.family} LoRA training requires bf16: fp16 overflows its fp32 RoPE / "
            f"embedder internals. Set mixed precision to bf16."
        )

    import torch

    rng = random.Random(cfg.seed)
    torch.manual_seed(cfg.seed)
    _FLUX_STATIC.clear()

    save_on_stop = True

    def _check_stop() -> bool:
        nonlocal save_on_stop

View on GitHub (pinned to 203007d190)

Solutions

  1. Check the supported families in the trainer docstring (FLUX.1 / FLUX.2 / Qwen-Image / Z-Image / Krea 2 / LTX-2) and set base_model to one of those.
  2. Print cfg.resolved_family after config.normalized() to see what the family actually resolved to and fix the source of the bad value.
  3. Align versions: update the backend so the family your config references is registered in _SPECS.

Example fix

# before
cfg.resolved_family = "flux.3"  # not a real family -> No DiT trainer

# after
cfg.base_model = "black-forest-labs/FLUX.1-dev"  # normalization resolves a known family
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {"flux.1", "flux.2", "qwen-image", "z-image", "krea-2", "ltx-2"}  # mirror _SPECS keys

def family_supported(resolved_family: str) -> bool:
    return resolved_family in SUPPORTED

Try / catch

try:
    train_diT_lora(cfg)
except ValueError as e:
    if "No DiT trainer for family" in str(e):
        raise SystemExit(f"Unknown family {cfg.resolved_family!r}; check base_model spelling/backend version")
    raise

Prevention

When it happens

Trigger: cfg.resolved_family resolving to a string not present in _SPECS: a typo or custom family name injected into the config, a new model family saved by a newer Studio version then opened by an older backend, or direct API calls constructing configs by hand.

Common situations: Downgrading the backend or mixing backend/frontend versions; hand-written config dicts; a family constant renamed between releases; custom forks adding a family without registering a spec.

Related errors


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