unslothai/unsloth · error · ValueError
mixed_precision must be one of bf16 / fp16 / no
Error message
mixed_precision must be one of bf16 / fp16 / no
What it means
The validator rejected a mixed_precision value outside the allowed set ('bf16', 'fp16', 'no'). This field selects the training compute dtype; anything else (including casing variants or synonyms like 'float16') is a configuration typo that would otherwise fail deep in the trainer. The check is case-sensitive as written.
Source
Thrown at studio/backend/core/training/diffusion_train_common.py:1035
if self.lora_alpha is not None and self.lora_alpha < 1:
raise ValueError(
"lora_alpha must be >= 1 (a zero/negative alpha scales the adapter to nothing)"
)
if self.resolution < 64 or self.resolution % 8 != 0:
raise ValueError("resolution must be a multiple of 8 and >= 64")
# A video family's VAE compresses space by 32, so an off-grid resolution changes the
# latent geometry silently. Refuse it here, before the GPU models are evicted.
if (
resolved_family in TRAINABLE_VIDEO_FAMILIES
and self.resolution % _VIDEO_RESOLUTION_MULTIPLE != 0
):
raise ValueError(
f"'{resolved_family}' trains at a resolution that is a multiple of "
f"{_VIDEO_RESOLUTION_MULTIPLE} (its VAE compresses space by that factor); "
f"got {self.resolution}."
)
if self.mixed_precision not in ("bf16", "fp16", "no"):
raise ValueError("mixed_precision must be one of bf16 / fp16 / no")
# torch.manual_seed unpacks int64/uint64, so anything wider raises inside the trainer, after eviction. Catch it here.
if not -(2**63) <= int(self.seed) <= 2**64 - 1:
raise ValueError("seed must fit in torch's 64-bit range")
# Refuse fp16 for a bf16-only DiT family up front, before evicting resident models.
if self.mixed_precision == "fp16" and resolved_family in _FORCE_BF16_FAMILIES:
raise ValueError(
f"'{resolved_family}' LoRA training requires bf16: fp16 overflows its fp32 "
f"RoPE / embedder internals. Set mixed precision to bf16."
)
if str(self.lr_scheduler) not in _LR_SCHEDULERS:
raise ValueError(
f"lr_scheduler must be one of {', '.join(sorted(_LR_SCHEDULERS))}; "
f"got {self.lr_scheduler!r}"
)
if not 1 <= int(self.cache_variants) <= 16:
raise ValueError("cache_variants must be between 1 and 16")
# Checkpointing knobs. Rejected here, before the route evicts resident GPU models, rather than deep in the loop.
try:View on GitHub (pinned to 203007d190)
Solutions
- Use exactly one of: 'bf16', 'fp16', 'no'.
- Normalize before submitting: mixed_precision = str(v).strip().lower().
- If you meant full fp32 training, the value is 'no', not 'fp32'.
Example fix
# before config = TrainConfig(mixed_precision='float16') # after config = TrainConfig(mixed_precision='fp16')
Defensive patterns
Strategy: validation
Validate before calling
VALID_MIXED_PRECISION = {"bf16", "fp16", "no"}
def check_mixed_precision(v) -> str:
p = str(v or "no").strip().lower()
alias = {"float16": "fp16", "half": "fp16", "fp32": "no", "float32": "no", "full": "no"}
p = alias.get(p, p)
if p not in VALID_MIXED_PRECISION:
raise ValueError(f"mixed_precision must be one of bf16 / fp16 / no, got {v!r}")
return p Type guard
def is_valid_mixed_precision(v) -> bool:
return str(v or "no").strip().lower() in {"bf16", "fp16", "no"} Try / catch
try:
session.submit_training(config)
except ValueError as e:
if "mixed_precision" in str(e):
config.mixed_precision = "bf16" # safe modern default
session.submit_training(config)
else:
raise Prevention
- Normalize with strip().lower() before submitting — the validator compares the raw value.
- Use a closed dropdown (bf16/fp16/no), never free text, for this field.
- Map other frameworks' spellings (float16/half/fp32) at your boundary, not in configs.
When it happens
Trigger: Passing mixed_precision='float16', 'fp32', 'bf16 ' (trailing whitespace), 'FP16', or None-adjacent garbage. Note the code compares self.mixed_precision directly, so unlike other fields here there is no .strip().lower() coercion — even a valid value with different casing fails.
Common situations: Configs written from memory with dtype spellings from other frameworks ('float16', 'half'); copy-paste between tools that use different vocabularies; uppercase values from UI dropdowns that normalize labels.
Related errors
- gradient_accumulation_steps must be >= 1
- lora_rank must be >= 1
- lora_alpha must be >= 1 (a zero/negative alpha scales the ad
- resolution must be a multiple of 8 and >= 64
- seed must fit in torch's 64-bit range
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/6e3fe4004ba7300b.
Report an issue: GitHub.