unslothai/unsloth · error · ValueError

Unsupported diffusion speed_mode '{value}'. Use one of: {',

Error message

Unsupported diffusion speed_mode '{value}'. Use one of: {', '.join(SPEED_MODES)}.

What it means

normalize_speed_mode validates the diffusion speed_mode parameter: None and empty string map to SPEED_OFF, dashes are normalized to underscores, and the result must be in SPEED_MODES ('off', 'eager', 'default', 'max'). Anything else raises ValueError so the route rejects the request before GPU work.

Source

Thrown at studio/backend/core/inference/diffusion_speed.py:120

def _inductor_config() -> Any:
    """``torch._inductor.config`` or None. Read as attributes off the imported torch (not a
    submodule import) so a stubbed/partial torch reports None instead of a stale sys.modules hit."""
    try:
        import torch
        return getattr(getattr(torch, "_inductor", None), "config", None)
    except Exception:  # noqa: BLE001 — no inductor -> nothing to snapshot/set
        return None


def normalize_speed_mode(value: Optional[str]) -> str:
    """Lower/strip a requested speed mode (dashes ok); None / "" -> off."""
    if value is None:
        return SPEED_OFF
    normalized = str(value).strip().lower().replace("-", "_")
    if not normalized:
        return SPEED_OFF
    if normalized not in SPEED_MODES:
        raise ValueError(
            f"Unsupported diffusion speed_mode '{value}'. Use one of: {', '.join(SPEED_MODES)}."
        )
    return normalized


def resolve_speed_mode(
    value: Optional[str],
    *,
    is_gguf: bool,
    dense_default: str = SPEED_OFF,
) -> str:
    """The effective speed mode when the caller leaves it UNSET (``None``).

    GGUF defaults to ``default``: compiles only the hot dequant op chain (~70-80% of eager GGUF
    time) for ~1.24-1.64x at a small compile, zero extra VRAM, perturbation below the quant noise
    floor. Dense resolves to ``dense_default``: the image backend keeps ``off`` (bit-identical
    first generations, deferred engagement), the video backend passes ``default`` (a clip denoise
    amortises the compile within one generation). An explicit value (incl. ``"off"``) is honored."""

View on GitHub (pinned to 203007d190)

Solutions

  1. Send one of: off, eager, default, max ('max' maps to full inductor compilation)
  2. Omit speed_mode or send null/'' to run uncompiled (off)
  3. Check the deployed backend's SPEED_MODES if the client is newer

Example fix

// before
{"speed_mode": "turbo"}
// after
{"speed_mode": "max"}
Defensive patterns

Strategy: validation

Validate before calling

SPEED = {"off", "eager", "default", "max"}

def valid_speed_mode(v) -> bool:
    if v is None:
        return True
    n = str(v).strip().lower().replace("-", "_")
    return n in SPEED | {""}

Type guard

def is_speed_mode(v) -> bool:
    return v is None or (isinstance(v, str) and str(v).strip().lower().replace("-", "_") in {"", "off", "eager", "default", "max"})

Try / catch

try:
    normalize_speed_mode(req.speed_mode)
except ValueError as e:
    return JSONResponse(status_code=400, content={"detail": str(e)})

Prevention

When it happens

Trigger: Request with speed_mode like 'turbo', 'fastest', 'full', or a typo like 'defualt' — any string not normalizing to off/eager/default/max.

Common situations: UI dropdown out of sync with backend vocabulary; clients forwarding sampler-name or profile strings into speed_mode; version skew between client and server.

Related errors


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