{"record":{"id":"211ad0fb95a38755","repo":"invoke-ai/InvokeAI","slug":"model-architecture-class-name-is-not-a-causal","errorCode":null,"errorMessage":"model architecture '{class_name}' is not a causal language model","messagePattern":"model architecture '(.+?)' is not a causal language model","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/text_llm.py","lineNumber":48,"sourceCode":"    \"\"\"Model config for text-only causal language models (e.g. Llama, Phi, Qwen, Mistral).\"\"\"\n\n    type: Literal[ModelType.TextLLM] = Field(default=ModelType.TextLLM)\n    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)\n    cpu_only: bool | None = Field(default=None, description=\"Whether this model should run on CPU only\")\n\n    @classmethod\n    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:\n        raise_if_not_dir(mod)\n\n        raise_for_override_fields(cls, override_fields)\n\n        # Check that the model's architecture is a causal language model.\n        # This covers LlamaForCausalLM, PhiForCausalLM, Phi3ForCausalLM, Qwen2ForCausalLM,\n        # MistralForCausalLM, GemmaForCausalLM, GPTNeoXForCausalLM, etc.\n        config_dict = get_config_dict_or_raise(common_config_paths(mod.path))\n        class_name = get_class_name_from_config_dict_or_raise(config_dict)\n        if not class_name.endswith(\"ForCausalLM\"):\n            raise NotAMatchError(f\"model architecture '{class_name}' is not a causal language model\")\n\n        # During *automatic* classification, defer to the dedicated PiD Gemma2 encoder config — but only\n        # for the hidden size that config actually accepts (2304 = Gemma-2-2b). Larger Gemma 2 variants\n        # (9B=3584, 27B=4608) are rejected by the encoder config, so they must remain classifiable as a\n        # generic TextLLM here rather than falling through to Unknown. An explicit `type=text_llm` request\n        # always keeps the model as TextLLM (the generic AutoModelForCausalLM loader supports these).\n        explicitly_requested_text_llm = override_fields.get(\"type\") == ModelType.TextLLM\n        if (\n            not explicitly_requested_text_llm\n            and class_name == \"Gemma2ForCausalLM\"\n            and config_dict.get(\"hidden_size\") == _GEMMA2_2B_HIDDEN_SIZE\n        ):\n            raise NotAMatchError(\n                \"architecture 'Gemma2ForCausalLM' (2304-dim Gemma-2-2b) is handled by the PiD encoder config, not TextLLM\"\n            )\n\n        # Verify tokenizer files exist to avoid runtime failures\n        tokenizer_files = {\"tokenizer.json\", \"tokenizer.model\", \"tokenizer_config.json\"}","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/text_llm.py#L30-L66","documentation":"NotAMatchError from TextLLM from_model_on_disk. The generic text-LLM config only accepts causal language model architectures: the config dict's architecture class name must end with 'ForCausalLM' (LlamaForCausalLM, Phi3ForCausalLM, Qwen2ForCausalLM, etc.). Anything else (encoders, seq2seq, vision models) is rejected as not a supported causal LM.","triggerScenarios":"from_model_on_disk on a model whose config.json 'architectures' class does not end with 'ForCausalLM' — e.g. T5ForConditionalGeneration, BertModel, CLIPTextModel, or a malformed config.json missing 'architectures'.","commonSituations":"Trying to load encoder-only or encoder-decoder models (T5, BERT, CLIP) as chat LLMs, embedding models, or configs whose architectures entry was edited/stripped.","solutions":["Use a model with a *ForCausalLM architecture (Llama, Qwen2, Phi3, Mistral, Gemma, GPTNeoX families)","Fix config.json 'architectures' if it was corrupted, using the value from the upstream repo","Register encoder/seq2seq models under their appropriate InvokeAI model type instead of text_llm"],"exampleFix":"// before\n{\"architectures\": [\"T5EncoderModel\"], ...}\n// after\n{\"architectures\": [\"Qwen2ForCausalLM\"], ...}  # or use a causal-LM model","handlingStrategy":"validation","validationCode":"import json\ndef is_causal_lm(model_dir) -> bool:\n    cfg = json.loads((model_dir / \"config.json\").read_text())\n    archs = cfg.get(\"architectures\", [])\n    return bool(archs) and archs[0].endswith(\"ForCausalLM\")","typeGuard":null,"tryCatchPattern":"try:\n    install_model(path, type=\"text_llm\")\nexcept NotAMatchError as e:\n    if \"causal language model\" in str(e):\n        logger.error(\"Architecture is not *ForCausalLM; choose an encoder/seq2seq-appropriate type\")","preventionTips":["Check config.json 'architectures' before adding a model as text_llm","Only use *ForCausalLM models (Llama/Qwen2/Phi3/Mistral/Gemma) as text LLMs","Don't hand-edit config.json architectures"],"tags":["architecture","text-llm","config"],"backgroundTag":"unsupported-model-architecture","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}