{"record":{"id":"fda456af65f5d53c","repo":"invoke-ai/InvokeAI","slug":"state-dict-does-not-look-like-bnb-quantized-nf4","errorCode":null,"errorMessage":"state dict does not look like bnb quantized nf4","messagePattern":"state dict does not look like bnb quantized nf4","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"warning","filePath":"invokeai/backend/model_manager/configs/main.py","lineNumber":808,"sourceCode":"        if variant is None:\n            # TODO(psyche): Should we have a graceful fallback here? Previously we fell back to the \"normal\" variant,\n            # but this variant is no longer used for FLUX models. If we get here, but the model is definitely a FLUX\n            # model, we should figure out a good fallback value.\n            raise NotAMatchError(\"unable to determine model variant from state dict\")\n\n        return variant\n\n    @classmethod\n    def _validate_looks_like_main_model(cls, mod: ModelOnDisk) -> None:\n        has_main_model_keys = _has_main_keys(mod.load_state_dict())\n        if not has_main_model_keys:\n            raise NotAMatchError(\"state dict does not look like a main model\")\n\n    @classmethod\n    def _validate_model_looks_like_bnb_quantized(cls, mod: ModelOnDisk) -> None:\n        has_bnb_nf4_keys = _has_bnb_nf4_keys(mod.load_state_dict())\n        if not has_bnb_nf4_keys:\n            raise NotAMatchError(\"state dict does not look like bnb quantized nf4\")\n\n\nclass Main_GGUF_FLUX_Config(Checkpoint_Config_Base, Main_Config_Base, Config_Base):\n    \"\"\"Model config for main checkpoint models.\"\"\"\n\n    base: Literal[BaseModelType.Flux] = Field(default=BaseModelType.Flux)\n    format: Literal[ModelFormat.GGUFQuantized] = Field(default=ModelFormat.GGUFQuantized)\n\n    variant: FluxVariantType = Field()\n\n    @classmethod\n    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:\n        raise_if_not_file(mod)\n\n        raise_for_override_fields(cls, override_fields)\n\n        cls._validate_looks_like_main_model(mod)\n","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/main.py#L790-L826","documentation":"Main_BnBNF4_FLUX_Config.from_model_on_disk calls _validate_model_looks_like_bnb_quantized, which checks the state dict for bitsandbytes NF4 quantization keys (e.g. \"double_blocks.0.img_attn.proj.weight.quant_state.bitsandbytes__nf4\" per _has_bnb_nf4_keys). If no such quant_state key exists, the file is not an NF4-quantized checkpoint, so NotAMatchError is raised. It is a probe rejection during model scan: the correct (non-quantized) FLUX config class will be attempted next.","triggerScenarios":"Scanning/importing a FLUX checkpoint file with this config class when the file is a plain fp16/fp8 safetensors (no bnb quant_state keys), or a GGUF quantization, or the quant_state key layout differs from the two known prefixes.","commonSituations":"Downloading the fp16 FLUX.1-dev checkpoint and expecting it to load as bnb-NF4; upgrading InvokeAI and an older NF4 export uses key names the current detector does not recognize; bitsandbytes re-quantized model saved without quant_state metadata.","solutions":["Import the model as a normal (non-NF4) FLUX main checkpoint; InvokeAI will fall through to Main_Checkpoint_FLUX_Config.","If NF4 is required, re-quantize with bitsandbytes ensuring quant_state is stored under one of the recognized keys (double_blocks.0...quant_state.bitsandbytes__nf4).","Check the download actually is the NF4 variant (file size ~half of fp16); re-download if not.","Update InvokeAI if you have a newer bnb/NF4 layout not yet covered by _has_bnb_nf4_keys."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"from safetensors import safe_open\n\ndef is_bnb_nf4(path):\n    targets = (\"double_blocks.0.img_attn.proj.weight.quant_state.bitsandbytes__nf4\",\n               \"model.diffusion_model.double_blocks.0.img_attn.proj.weight.quant_state.bitsandbytes__nf4\")\n    with safe_open(path, framework=\"pt\") as f:\n        keys = set(f.keys())\n    return any(t in keys for t in targets)\n\nif not is_bnb_nf4(path):\n    print(\"not NF4-quantized - import as a regular checkpoint\")","typeGuard":"def is_bnb_nf4_state_dict(sd: dict) -> bool:\n    return any(k in sd for k in (\n        \"double_blocks.0.img_attn.proj.weight.quant_state.bitsandbytes__nf4\",\n        \"model.diffusion_model.double_blocks.0.img_attn.proj.weight.quant_state.bitsandbytes__nf4\",\n    ))","tryCatchPattern":"try:\n    cfg = Main_BnBNF4_FLUX_Config.from_model_on_disk(mod)\nexcept NotAMatchError:\n    cfg = Main_Checkpoint_FLUX_Config.from_model_on_disk(mod)  # fall back to the unquantized config","preventionTips":["Download the NF4 build deliberately (it is roughly half the fp16 file size).","Re-quantize with bitsandbytes keeping quant_state stored in the checkpoint.","Don't rename files across quantization types; keep releases separate.","Prefer letting InvokeAI auto-detect instead of forcing a quantized model type."],"tags":["quantization","bitsandbytes","nf4","state-dict"],"backgroundTag":"model-not-matching-config","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}