invoke-ai/InvokeAI · error · ValueError

LLLite module '{name}' targets block {block_idx}, but the tr

Error message

LLLite module '{name}' targets block {block_idx}, but the transformer has only {len(blocks)} blocks

What it means

After the module name parses, _resolve_target checks the block index against the transformer's actual depth. If the name targets block N but transformer.blocks has fewer than N+1 blocks, the layer does not exist and the library raises ValueError rather than indexing out of range.

Source

Thrown at invokeai/backend/anima/control_net_lllite.py:547

        LIFO contract: each bind saves the forward that was CURRENT at bind
        time, so when multiple adapters are stacked on one transformer they
        must be restored in reverse apply order. Restoring an earlier adapter
        first would delete a later adapter's wrapper and re-pin the earlier
        one's saved forward.
        """
        for m in self.lllite_modules:
            m.unbind()

    @staticmethod
    def _resolve_target(transformer: nn.Module, name: str) -> nn.Module:
        match = MODULE_NAME_PATTERN.match(name)
        if match is None:
            raise ValueError(f"Unrecognized LLLite module name: '{name}'")
        block_idx = int(match.group(1))
        blocks = transformer.blocks
        if block_idx >= len(blocks):
            raise ValueError(
                f"LLLite module '{name}' targets block {block_idx}, but the transformer has only {len(blocks)} blocks"
            )
        target: nn.Module = blocks[block_idx]
        for attr in _SUFFIX_TO_ATTR_PATH[match.group(2)]:
            target = getattr(target, attr)
        return target

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Match the adapter to a base transformer with at least as many blocks as it targets.
  2. Filter out or remap adapter entries whose block indices exceed len(transformer.blocks).
  3. Verify model config (number of transformer blocks) hasn't changed relative to the adapter's training config.

Example fix

// before
lllite.apply_to(transformer_distilled)  # 28 blocks, adapter targets block 30
// after
lllite.apply_to(transformer_full)  # 36 blocks, matches adapter
Defensive patterns

Strategy: validation

Validate before calling

max_block = max(int(re.search(r"blocks(\d+)", m["lllite_name"]).group(1)) for m in adapter_modules)
assert max_block < len(transformer.blocks)

Type guard

def fits_transformer(names: list[str], transformer) -> bool:
    return all(int(n.split("blocks")[1].split(".")[0] if "." in n else re.search(r"\d+", n).group()) < len(transformer.blocks) for n in names)

Try / catch

try:
    lllite.apply_to(transformer)
except ValueError as e:
    if "has only" in str(e):
        logger.error("Adapter targets a deeper transformer than loaded: %s", e)
    raise

Prevention

When it happens

Trigger: apply_to(transformer) where an adapter name like 'blocks30.ff.net.0.proj' is applied to a transformer with e.g. 28 blocks — a shallower model than the adapter was trained on.

Common situations: Adapter trained on a deep (e.g. 36-block) Anima model applied to a distilled or smaller variant; changed num_blocks in model config after adapter training.

Related errors


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