{"record":{"id":"6e3fe4004ba7300b","repo":"unslothai/unsloth","slug":"mixed-precision-must-be-one-of-bf16-fp16-no","errorCode":null,"errorMessage":"mixed_precision must be one of bf16 / fp16 / no","messagePattern":"mixed_precision must be one of bf16 / fp16 / no","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_train_common.py","lineNumber":1035,"sourceCode":"        if self.lora_alpha is not None and self.lora_alpha < 1:\n            raise ValueError(\n                \"lora_alpha must be >= 1 (a zero/negative alpha scales the adapter to nothing)\"\n            )\n        if self.resolution < 64 or self.resolution % 8 != 0:\n            raise ValueError(\"resolution must be a multiple of 8 and >= 64\")\n        # A video family's VAE compresses space by 32, so an off-grid resolution changes the\n        # latent geometry silently. Refuse it here, before the GPU models are evicted.\n        if (\n            resolved_family in TRAINABLE_VIDEO_FAMILIES\n            and self.resolution % _VIDEO_RESOLUTION_MULTIPLE != 0\n        ):\n            raise ValueError(\n                f\"'{resolved_family}' trains at a resolution that is a multiple of \"\n                f\"{_VIDEO_RESOLUTION_MULTIPLE} (its VAE compresses space by that factor); \"\n                f\"got {self.resolution}.\"\n            )\n        if self.mixed_precision not in (\"bf16\", \"fp16\", \"no\"):\n            raise ValueError(\"mixed_precision must be one of bf16 / fp16 / no\")\n        # torch.manual_seed unpacks int64/uint64, so anything wider raises inside the trainer, after eviction. Catch it here.\n        if not -(2**63) <= int(self.seed) <= 2**64 - 1:\n            raise ValueError(\"seed must fit in torch's 64-bit range\")\n        # Refuse fp16 for a bf16-only DiT family up front, before evicting resident models.\n        if self.mixed_precision == \"fp16\" and resolved_family in _FORCE_BF16_FAMILIES:\n            raise ValueError(\n                f\"'{resolved_family}' LoRA training requires bf16: fp16 overflows its fp32 \"\n                f\"RoPE / embedder internals. Set mixed precision to bf16.\"\n            )\n        if str(self.lr_scheduler) not in _LR_SCHEDULERS:\n            raise ValueError(\n                f\"lr_scheduler must be one of {', '.join(sorted(_LR_SCHEDULERS))}; \"\n                f\"got {self.lr_scheduler!r}\"\n            )\n        if not 1 <= int(self.cache_variants) <= 16:\n            raise ValueError(\"cache_variants must be between 1 and 16\")\n        # Checkpointing knobs. Rejected here, before the route evicts resident GPU models, rather than deep in the loop.\n        try:","sourceCodeStart":1017,"sourceCodeEnd":1053,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_train_common.py#L1017-L1053","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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'."],"exampleFix":"# before\nconfig = TrainConfig(mixed_precision='float16')\n\n# after\nconfig = TrainConfig(mixed_precision='fp16')","handlingStrategy":"validation","validationCode":"VALID_MIXED_PRECISION = {\"bf16\", \"fp16\", \"no\"}\n\ndef check_mixed_precision(v) -> str:\n    p = str(v or \"no\").strip().lower()\n    alias = {\"float16\": \"fp16\", \"half\": \"fp16\", \"fp32\": \"no\", \"float32\": \"no\", \"full\": \"no\"}\n    p = alias.get(p, p)\n    if p not in VALID_MIXED_PRECISION:\n        raise ValueError(f\"mixed_precision must be one of bf16 / fp16 / no, got {v!r}\")\n    return p","typeGuard":"def is_valid_mixed_precision(v) -> bool:\n    return str(v or \"no\").strip().lower() in {\"bf16\", \"fp16\", \"no\"}","tryCatchPattern":"try:\n    session.submit_training(config)\nexcept ValueError as e:\n    if \"mixed_precision\" in str(e):\n        config.mixed_precision = \"bf16\"  # safe modern default\n        session.submit_training(config)\n    else:\n        raise","preventionTips":["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."],"tags":["training","mixed-precision","configuration","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}