{"record":{"id":"d557f98d04da4704","repo":"invoke-ai/InvokeAI","slug":"folder-is-sdnq-quantized-use-qwen3encoder-sdnq-fo","errorCode":null,"errorMessage":"folder is SDNQ-quantized; use Qwen3Encoder_SDNQ_Folder_Config","messagePattern":"folder is SDNQ-quantized; use Qwen3Encoder_SDNQ_Folder_Config","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"warning","filePath":"invokeai/backend/model_manager/configs/qwen3_encoder.py","lineNumber":358,"sourceCode":"\n        return cls(variant=variant, **override_fields)\n\n    @classmethod\n    def _reject_if_sdnq_quantized(cls, mod: ModelOnDisk) -> None:\n        # Primary signal: quantization_config.json with quant_method=\"sdnq\" (at root or in\n        # text_encoder/). Fallback: SDNQ-style weight+scale key pairs in the state dict. This mirrors\n        # the detection in Qwen3Encoder_SDNQ_Folder_Config so the two stay mutually exclusive.\n        for folder in (mod.path, mod.path / \"text_encoder\"):\n            quant_config_path = folder / \"quantization_config.json\"\n            if not quant_config_path.exists():\n                continue\n            try:\n                with open(quant_config_path, \"r\", encoding=\"utf-8\") as f:\n                    quant_config = json.load(f)\n            except (json.JSONDecodeError, OSError):\n                continue\n            if quant_config.get(\"quant_method\") == \"sdnq\":\n                raise NotAMatchError(\"folder is SDNQ-quantized; use Qwen3Encoder_SDNQ_Folder_Config\")\n\n        if _has_sdnq_keys(mod.load_state_dict()):\n            raise NotAMatchError(\"state dict looks SDNQ-quantized; use Qwen3Encoder_SDNQ_Folder_Config\")\n\n    @classmethod\n    def _get_variant_from_config(cls, config_path) -> Qwen3VariantType:\n        \"\"\"Get variant from config.json based on hidden_size, or raise NotAMatch if unknown.\"\"\"\n        QWEN3_06B_HIDDEN_SIZE = 1024\n        QWEN3_4B_HIDDEN_SIZE = 2560\n        QWEN3_8B_HIDDEN_SIZE = 4096\n\n        try:\n            with open(config_path, \"r\", encoding=\"utf-8\") as f:\n                config = json.load(f)\n        except (json.JSONDecodeError, OSError) as e:\n            raise NotAMatchError(f\"unable to read Qwen3 config.json: {e}\") from e\n\n        hidden_size = config.get(\"hidden_size\")","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_encoder.py#L340-L376","documentation":"NotAMatchError raised by Qwen3Encoder_Qwen3Encoder_Config._reject_if_sdnq_quantized (qwen3_encoder.py:358). A quantization_config.json with quant_method=\"sdnq\" was found at the model root or in text_encoder/. The folder is an SDNQ-quantized Qwen3 encoder and must be matched by Qwen3Encoder_SDNQ_Folder_Config; the unquantized config rejects it so the two configs stay mutually exclusive and the correct (SDNQ) loader handles the packed weights.","triggerScenarios":"from_model_on_disk on a folder where quantization_config.json (root or text_encoder/) parses with quant_method == 'sdnq' while the unquantized Qwen3Encoder config probes it.","commonSituations":"Installing an SDNQ-quantized download of a Qwen3/Z-Image text encoder while expecting the standard (unquantized) Qwen3Encoder loader to run; upgrading a model to an SDNQ re-release without changing its registered config.","solutions":["Allow the scan to continue — Qwen3Encoder_SDNQ_Folder_Config should match the folder instead.","If it stays unidentified, explicitly register the model with the SDNQ Qwen3 encoder config/type.","To use the unquantized loader, download the non-SDNQ revision of the model.","If quantization_config.json is a stray leftover, remove it and rescan (only if weights truly are not SDNQ-quantized)."],"exampleFix":"// before\ninvokeai-install models/qwen3-encoder/  // contains quantization_config.json (quant_method: sdnq)\n// after\nregister models/qwen3-encoder/ with Qwen3Encoder_SDNQ_Folder_Config (or download the unquantized revision)","handlingStrategy":"validation","validationCode":"import json\ndef is_sdnq_folder(path) -> bool:\n    for folder in (path, path / 'text_encoder'):\n        q = folder / 'quantization_config.json'\n        if q.exists():\n            try:\n                if json.loads(q.read_text()).get('quant_method') == 'sdnq':\n                    return True\n            except (json.JSONDecodeError, OSError):\n                pass\n    return False  # if True, register with Qwen3Encoder_SDNQ_Folder_Config","typeGuard":"def needs_sdnq_config(path) -> bool:\n    import json\n    q = path / 'quantization_config.json'\n    alt = path / 'text_encoder' / 'quantization_config.json'\n    for f in (q, alt):\n        if f.exists() and json.loads(f.read_text()).get('quant_method') == 'sdnq':\n            return True\n    return False","tryCatchPattern":"if is_sdnq_folder(model_dir):\n    register_model(model_dir, config='Qwen3Encoder_SDNQ_Folder_Config')\nelse:\n    try:\n        register_model(model_dir, model_type='Qwen3Encoder')\n    except NotAMatchError as e:\n        logger.warning('Rejected: %s', e)","preventionTips":["Read quantization_config.json before installing and route SDNQ models to the SDNQ config.","Keep quantized and unquantized revisions in separate directories.","When upgrading to an SDNQ re-release, re-register the model under the SDNQ config."],"tags":["quantization","sdnq","model-identification","qwen3"],"backgroundTag":"quantized-model-config-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}