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_processor

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. 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).
  2. 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()}`.
  3. 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.
  4. 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.
  5. 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

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


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/c0f0cacdd74e129f. Report an issue: GitHub.