{"record":{"id":"2fe0e55b0a30c06e","repo":"unslothai/unsloth","slug":"base-precision-must-be-one-of-nf4-bf16-int8","errorCode":null,"errorMessage":"base_precision must be one of nf4 / bf16 / int8 / fp8 / mxfp8 / auto","messagePattern":"base_precision must be one of nf4 / bf16 / int8 / fp8 / mxfp8 / auto","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_train_common.py","lineNumber":1104,"sourceCode":"                    f\"checkpoint bundle. Leave it at 0; the adapter is still saved at the end.\"\n                )\n        try:\n            ema_decay = float(self.ema_decay or 0.0)\n        except (TypeError, ValueError) as exc:\n            raise ValueError(f\"ema_decay must be a number, got {self.ema_decay!r}\") from exc\n        # decay = 1.0 would freeze the shadow at its init forever; the update is shadow * decay + param * (1 - decay), so valid decays live in [0, 1).\n        if not 0.0 <= ema_decay < 1.0:\n            raise ValueError(\"ema_decay must be in [0, 1); 0 disables the EMA adapter\")\n        # A blank cond_cache_dir (the Studio default when unset) means \"off\", not cwd.\n        cond_cache_dir = (\n            str(self.cond_cache_dir).strip() if self.cond_cache_dir is not None else \"\"\n        ) or None\n        compile_transformer = str(self.compile_transformer or \"auto\").strip().lower()\n        if compile_transformer not in (\"off\", \"on\", \"auto\"):\n            raise ValueError(\"compile_transformer must be one of off / on / auto\")\n        base_precision = str(self.base_precision or \"nf4\").strip().lower()\n        if base_precision not in (\"nf4\", \"bf16\", \"int8\", \"fp8\", \"mxfp8\", \"auto\"):\n            raise ValueError(\"base_precision must be one of nf4 / bf16 / int8 / fp8 / mxfp8 / auto\")\n        # base_precision is a DiT-only lever, so the dense-mode gates apply only to the DiT families. The mode-name check above still runs for every family.\n        if resolved_family != \"sdxl\" and base_precision in (\"bf16\", \"int8\", \"fp8\", \"mxfp8\"):\n            if repo_is_prequantized(self.base_model):\n                raise ValueError(\n                    f\"base_precision={base_precision!r} needs a dense base repo, but \"\n                    f\"'{self.base_model}' is already bitsandbytes-quantized. Pick the \"\n                    f\"family's dense (bf16) base repo for this mode, or use nf4/auto.\"\n                )\n            if self.mixed_precision != \"bf16\":\n                raise ValueError(\n                    f\"base_precision={base_precision!r} trains in bf16 compute; set \"\n                    f\"mixed_precision to bf16.\"\n                )\n            # Refuse a scheme this family's DiT is known to corrupt, and also one the training bar holds back while\n            # inference allows it: qwen-image fp8 now renders inside the accuracy gate, but no one has measured whether a\n            # LoRA converges against fp8-frozen linears, so it fails fast here rather than silently training on faith.\n            # MiniMax-H3 runs all three modalities through one set of linears, so the\n            # per-family activation range the fp8 module filter was measured against does not","sourceCodeStart":1086,"sourceCodeEnd":1122,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_train_common.py#L1086-L1122","documentation":"The validator rejected a base_precision value outside ('nf4', 'bf16', 'int8', 'fp8', 'mxfp8', 'auto'). base_precision selects how the frozen base model's weights are quantized during LoRA training (NF4/INT8/FP8 via bitsandbytes, dense bf16, or 'auto'). The value is strip().lower()-ed first, so this error is purely about an unrecognized name.","triggerScenarios":"Passing base_precision='fp16' (not supported — fp16 is a compute precision, not a base quantization), '4bit', '8bit', 'q4', 'none', or spellings from other tools (GGUF names, 'awq', 'gptq').","commonSituations":"Copying quantization vocabulary from llama.cpp/GGUF or autogptq configs; confusion between mixed_precision (compute) and base_precision (weight storage); UI free-text entry.","solutions":["Use one of: nf4, bf16, int8, fp8, mxfp8, auto (case-insensitive).","For 4-bit use 'nf4'; for 8-bit use 'int8'; there is no fp16 option by design.","If unsure, 'auto' picks a sensible default for the family."],"exampleFix":"# before\nconfig = TrainConfig(base_precision='4bit')\n\n# after\nconfig = TrainConfig(base_precision='nf4')","handlingStrategy":"validation","validationCode":"VALID_BASE_PRECISION = {\"nf4\", \"bf16\", \"int8\", \"fp8\", \"mxfp8\", \"auto\"}\n\ndef check_base_precision(v) -> str:\n    s = str(v or \"nf4\").strip().lower()\n    alias = {\"4bit\": \"nf4\", \"nf4\": \"nf4\", \"8bit\": \"int8\", \"none\": \"auto\"}\n    s = alias.get(s, s)\n    if s not in VALID_BASE_PRECISION:\n        raise ValueError(f\"base_precision must be one of {sorted(VALID_BASE_PRECISION)}, got {v!r}\")\n    return s","typeGuard":"def is_valid_base_precision(v) -> bool:\n    return str(v or \"nf4\").strip().lower() in {\"nf4\", \"bf16\", \"int8\", \"fp8\", \"mxfp8\", \"auto\"}","tryCatchPattern":"try:\n    session.submit_training(config)\nexcept ValueError as e:\n    if \"base_precision must be one of\" in str(e):\n        config.base_precision = \"auto\"\n        session.submit_training(config)\n    else:\n        raise","preventionTips":["Keep mixed_precision (compute) and base_precision (weight quantization) straight — fp16 is never a base_precision.","Use the exact enum names (nf4/int8/fp8/mxfp8/bf16/auto), not GGUF/GPTQ vocabulary.","Use dropdowns sourced from the validator's allowlist."],"tags":["training","quantization","configuration","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}