invoke-ai/InvokeAI · warning · NotAMatchError
unable to load config file(s): {{PosixPath('{config_path_nes
Error message
unable to load config file(s): {{PosixPath('{config_path_nested}'): 'file does not exist'}} What it means
NotAMatchError raised in Qwen3Encoder_Qwen3Encoder_Config.from_model_on_disk (qwen3_encoder.py:324) when neither text_encoder/config.json nor config.json exists in the scanned directory. The message is phrased as a config-load failure naming the nested path, but its meaning is simply: this directory does not contain a Qwen3 encoder config.json, so this config does not match.
Source
Thrown at invokeai/backend/model_manager/configs/qwen3_encoder.py:324
# 1. Full model structure: model_root/text_encoder/config.json
# 2. Standalone text_encoder download: model_root/config.json (when text_encoder subfolder is downloaded separately)
config_path_nested = mod.path / "text_encoder" / "config.json"
config_path_direct = mod.path / "config.json"
if config_path_nested.exists():
expected_config_path = config_path_nested
elif config_path_direct.exists():
# Standalone text_encoder downloads do not bundle tokenizer files. If we see tokenizer files at the
# root next to config.json, this is a complete causal LM (TextLLM), not a Qwen3 encoder subfolder.
tokenizer_files = ("tokenizer.json", "tokenizer.model", "tokenizer_config.json")
if any((mod.path / f).exists() for f in tokenizer_files):
raise NotAMatchError(
"directory looks like a complete causal LM (config.json and tokenizer files at root), "
"not a standalone Qwen3 encoder"
)
expected_config_path = config_path_direct
else:
raise NotAMatchError(
f"unable to load config file(s): {{PosixPath('{config_path_nested}'): 'file does not exist'}}"
)
# Qwen3 uses Qwen2VLForConditionalGeneration or similar
raise_for_class_name(expected_config_path, _QWEN3_ENCODER_ARCHITECTURES)
# Reject SDNQ-quantized encoders so Qwen3Encoder_SDNQ_Folder_Config matches them instead.
# A real SDNQ Qwen3 encoder has the same Qwen3 config class name as an unquantized one, so
# without this guard both configs accept the folder — and since they share the Qwen3Encoder
# type, the factory tiebreak is non-deterministic. If it picked this (unquantized) config,
# the non-SDNQ loader would then mis-read the packed uint8 weights.
cls._reject_if_sdnq_quantized(mod)
# Determine variant from config.json hidden_size
variant = cls._get_variant_from_config(expected_config_path)
return cls(variant=variant, **override_fields)
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Ensure the directory contains config.json either at the root or under text_encoder/; re-download it from the model repo.
- Check for .no_exist / partial-download markers from huggingface_hub and retry the download.
- If this is a GGUF model, it will never have config.json here — install it via the GGUF flow instead.
- Point the scanner at the folder that actually holds the encoder config.
Example fix
// before models/qwen3-encoder/ // only model.safetensors // after models/qwen3-encoder/ // config.json + model.safetensors (config.json re-downloaded from the repo)
Defensive patterns
Strategy: validation
Validate before calling
def has_encoder_config(path) -> bool:
return (path / 'text_encoder' / 'config.json').exists() or (path / 'config.json').exists()
# call before install; if False, re-download config.json from the model repo Type guard
def encoder_config_path(path):
nested = path / 'text_encoder' / 'config.json'
direct = path / 'config.json'
if nested.exists():
return nested
if direct.exists():
return direct
return None # None means the Qwen3Encoder config will reject it Try / catch
cfg = encoder_config_path(model_dir)
if cfg is None:
raise FileNotFoundError(f'No config.json under {model_dir}; re-download from the model repo')
try:
register_model(model_dir, model_type='Qwen3Encoder')
except NotAMatchError as e:
logger.warning('Qwen3Encoder config rejected folder: %s', e) Prevention
- Always download config.json together with weight files (avoid *.safetensors-only downloads).
- After download, verify config.json exists before registering the model.
- Check for interrupted huggingface_hub snapshots (.incomplete / .no_exist markers).
When it happens
Trigger: from_model_on_disk on a directory where both mod.path/'text_encoder'/'config.json' and mod.path/'config.json' are missing — e.g. an empty folder, a folder with only weights and no config, or weights placed at the wrong nesting level.
Common situations: Interrupted HuggingFace downloads that skipped config.json; copying only *.safetensors files; scanning a GGUF directory (no config.json at all); pointing the scan at the model repo root when config.json lives in a differently named subfolder.
Related errors
- hidden size does not match a known Qwen3 variant
- state dict does not look like a Qwen3 model
- state dict looks like a T5 encoder (has 'enc.blk.*' keys), n
- state dict looks like a Gemma-2 encoder (has post_attention_
- state dict bundles a Qwen-VL visual tower; this is a Qwen-VL
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/fe69077fd28ec5eb.
Report an issue: GitHub.