invoke-ai/InvokeAI · error · ValueError
A dict of processors was passed, but the number of processor
Error message
A dict of processors was passed, but the number of processors {len(processor)} does not match the number of attention layers: {count}. Please make sure to pass {count} processor classes. What it means
`set_attn_processor` verifies that when a dict of attention processors is supplied, its number of entries equals the number of attention layers reported by `self.attn_processors`. A mismatch means the caller supplied processors for the wrong set of module names (or wrong model), so mapping modules to processors would silently skip or fail; the library raises this ValueError instead. This is standard diffusers `ModelMixin.set_attn_processor` behavior in InvokeAI's hotfixed copy.
Source
Thrown at invokeai/backend/util/hotfixes.py:475
# Copied from diffusers.models.unet_2d_condition.UNet2DConditionModel.set_attn_processor
def set_attn_processor(self, processor: Union[AttentionProcessor, Dict[str, AttentionProcessor]]):
r"""
Sets the attention processor to use to compute attention.
Parameters:
processor (`dict` of `AttentionProcessor` or only `AttentionProcessor`):
The instantiated processor class or a dictionary of processor classes that will be set as the processor
for **all** `Attention` layers.
If `processor` is a dict, the key needs to define the path to the corresponding cross attention
processor. This is strongly recommended when setting trainable attention processors.
"""
count = len(self.attn_processors.keys())
if isinstance(processor, dict) and len(processor) != count:
raise ValueError(
f"A dict of processors was passed, but the number of processors {len(processor)} does not match the"
f" number of attention layers: {count}. Please make sure to pass {count} processor classes."
)
def fn_recursive_attn_processor(name: str, module: torch.nn.Module, processor):
if hasattr(module, "set_processor"):
if not isinstance(processor, dict):
module.set_processor(processor)
else:
module.set_processor(processor.pop(f"{name}.processor"))
for sub_name, child in module.named_children():
fn_recursive_attn_processor(f"{name}.{sub_name}", child, processor)
for name, module in self.named_children():
fn_recursive_attn_processor(name, module, processor)
# Copied from diffusers.models.unet_2d_condition.UNet2DConditionModel.set_default_attn_processorView on GitHub (pinned to 0b6a024f2f)
Solutions
- Print `len(unet.attn_processors)` and `list(processor.keys())`; rebuild the dict so it has exactly one processor per key returned by `unet.attn_processors` (keys must match exactly).
- Build the dict programmatically from `unet.named_modules()` / `unet.attn_processors.keys()` instead of hardcoding names, e.g. `{k: MyAttnProcessor() for k in unet.attn_processors.keys()}`.
- Pass a single processor instance (or list) instead of a dict if you want the same processor applied to all layers — the count check only applies to dicts.
- Ensure IP-Adapter cross-attention processors are applied to the same UNet variant (SD1.5 vs SDXL) they were exported for; regenerate the processor dict if the base model changed.
- If a prior patch pass (LoRA/extension) altered the attention set, recompute processors after all other patches rather than caching them.
Example fix
// before
proc = {"down_blocks.0.attentions.0.transformer_blocks.0.attn1.processor": AttnProcessor2_0()}
unet.set_attn_processor(proc)
// after
from invokeai.backend.util.hotfixes import AttnProcessor2_0
proc = {name: AttnProcessor2_0() for name in unet.attn_processors.keys()}
assert len(proc) == len(unet.attn_processors)
unet.set_attn_processor(proc) Defensive patterns
Strategy: validation
Validate before calling
expected = set(unet.attn_processors.keys())
if isinstance(processor, dict) and set(processor.keys()) != expected:
missing = expected - set(processor.keys())
extra = set(processor.keys()) - expected
raise ValueError(f"processor keys mismatch; missing={sorted(missing)} extra={sorted(extra)}") Type guard
def processors_match(unet, processor) -> bool:
return not isinstance(processor, dict) or set(processor.keys()) == set(unet.attn_processors.keys()) Try / catch
try:
unet.set_attn_processor(processor)
except ValueError as e:
if "number of processors" in str(e):
from invokeai.backend.util.hotfixes import AttnProcessor2_0
processor = {name: AttnProcessor2_0() for name in unet.attn_processors.keys()}
unet.set_attn_processor(processor)
else:
raise Prevention
- Always build processor dicts from `unet.attn_processors.keys()`, never hardcoded layer names.
- Recompute the processor dict after any other patching (LoRA, xformers, extensions) changes the UNet.
- Only reuse IP-Adapter processor dicts with the exact UNet variant they were exported for (SD1.5 vs SDXL).
- Before calling set_attn_processor, assert set equality of dict keys against attn_processors keys to get a precise diff instead of a count mismatch.
When it happens
Trigger: Calling `unet.set_attn_processor(processor_dict)` where processor_dict keys/size don't match `unet.attn_processor` — e.g. building a dict for a different model, reusing an IP-Adapter processor dict across differently-patched UNets, or patching after LoRA/extension code changed the attention module set. Raised from set_attn_processor, invoked by _run_diffusion, patch_unet_attention_processor, apply_ip_adapter_attention, patch_extension, and set_default_attn_processor.
Common situations: IP-Adapter application to a UNet whose attention layer names differ from the ones the adapter bundle was built for (different SD1.5 vs SDXL UNets, or xformers/PyTorch 2.0 renaming); mixing processors computed before and after another patch pass; setting default processors on a model with extra controlnet attention modules.
Related errors
- Unsupported IP-Adapter type: {type(self.ip_adapter)}
- Unsupported IP-Adapter image type: {type(ip_adapter_field.im
- FLUX IP-Adapter only supports a single image prompt (receive
- IP-Adapter masks are not yet supported in Flux.
- {self.__class__} has the config param `encoder_hid_dim_type`
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/c0f0cacdd74e129f.
Report an issue: GitHub.