{"record":{"id":"573cbaeddfb8aa06","repo":"invoke-ai/InvokeAI","slug":"model-path-is-not-a-directory","errorCode":null,"errorMessage":"model path is not a directory","messagePattern":"model path is not a directory","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/identification_utils.py","lineNumber":166,"sourceCode":"    for field_name, override_value in override_fields.items():\n        if field_name not in candidate_config_class.model_fields:\n            raise NotAMatchError(f\"unknown override field: {field_name}\")\n        try:\n            PydanticFieldValidator.validate_field(candidate_config_class, field_name, override_value)\n        except ValidationError as e:\n            raise NotAMatchError(f\"invalid override for field '{field_name}': {e}\") from e\n\n\ndef raise_if_not_file(mod: ModelOnDisk) -> None:\n    \"\"\"Raise NotAMatch if the model path is not a file.\"\"\"\n    if not mod.path.is_file():\n        raise NotAMatchError(\"model path is not a file\")\n\n\ndef raise_if_not_dir(mod: ModelOnDisk) -> None:\n    \"\"\"Raise NotAMatch if the model path is not a directory.\"\"\"\n    if not mod.path.is_dir():\n        raise NotAMatchError(\"model path is not a directory\")\n\n\ndef state_dict_has_any_keys_exact(state_dict: dict[str | int, Any], keys: str | set[str]) -> bool:\n    \"\"\"Returns true if the state dict has any of the specified keys.\"\"\"\n    _keys = {keys} if isinstance(keys, str) else keys\n    return any(key in state_dict for key in _keys)\n\n\ndef state_dict_has_any_keys_starting_with(state_dict: dict[str | int, Any], prefixes: str | set[str]) -> bool:\n    \"\"\"Returns true if the state dict has any keys starting with any of the specified prefixes.\"\"\"\n    _prefixes = {prefixes} if isinstance(prefixes, str) else prefixes\n    return any(any(key.startswith(prefix) for prefix in _prefixes) for key in state_dict.keys() if isinstance(key, str))\n\n\ndef state_dict_has_any_keys_ending_with(state_dict: dict[str | int, Any], suffixes: str | set[str]) -> bool:\n    \"\"\"Returns true if the state dict has any keys ending with any of the specified suffixes.\"\"\"\n    _suffixes = {suffixes} if isinstance(suffixes, str) else suffixes\n    return any(any(key.endswith(suffix) for suffix in _suffixes) for key in state_dict.keys() if isinstance(key, str))","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/identification_utils.py#L148-L184","documentation":"raise_if_not_dir asserts that the ModelOnDisk path is a directory. Config classes for diffusers-style formats (which consist of a folder with config.json plus weight files) call this during from_model_on_disk; a plain file path fails the check with NotAMatchError so other config classes can be attempted.","triggerScenarios":"from_model_on_disk probing a diffusers/folder-based config class against a single .safetensors or .ckpt file path.","commonSituations":"Registering a single checkpoint file where a converted diffusers folder is expected; users placing a file where the scanner expects a repo-style directory; incomplete conversions leaving only files, not the expected folder layout.","solutions":["Pass the diffusers model directory (the folder containing model_index.json/config.json) instead of the weights file.","Convert the single-file checkpoint to diffusers format (e.g. diffusers conversion script) to obtain the expected folder layout.","If the model really is single-file, use the matching single-file config class.","Confirm the directory exists and is not a symlink to a file."],"exampleFix":"// before\nModelOnDisk(Path(\"/models/flux/flux1-dev.safetensors\"))\n// after\nModelOnDisk(Path(\"/models/flux/flux1-dev\"))  # diffusers directory","handlingStrategy":"validation","validationCode":"from pathlib import Path\np = Path(model_path)\nassert p.is_dir() and (p / \"model_index.json\").exists(), f\"expected a diffusers model directory: {p}\"","typeGuard":"def is_diffusers_dir(p) -> bool:\n    from pathlib import Path\n    d = Path(p)\n    return d.is_dir() and ((d / \"model_index.json\").exists() or (d / \"config.json\").exists())","tryCatchPattern":"try:\n    record = from_model_on_disk(mod)\nexcept NotAMatchError as e:\n    if str(e) == \"model path is not a directory\":\n        logger.warning(\"single file probed with directory config; will retry file-based config\")","preventionTips":["Register diffusers models by their top-level folder, not the weights file inside it","Convert single-file checkpoints to diffusers layout before folder-based registration","Verify model_index.json exists after any conversion"],"tags":["filesystem","path","invokeai"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}