invoke-ai/InvokeAI · error · ValueError

State dict appears to be in a legacy ControlNet-LLLite weigh

Error message

State dict appears to be in a legacy ControlNet-LLLite weight format (keys starting with '{_LEGACY_MODULES_PREFIX}'). Only the v2 named-key format is supported.

What it means

from_state_dict only supports the v2 named-key ControlNet-LLLite format. If any key starts with _LEGACY_MODULES_PREFIX (the legacy 'lllite_modules.' layout), it raises ValueError telling you to convert the checkpoint. Legacy keys lack the per-module names needed to resolve injection targets.

Source

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

            if MODULE_NAME_PATTERN.match(name) is None:
                raise ValueError(f"Unrecognized LLLite module name: '{name}'")
            modules.append(LLLiteModuleDiT(name, in_dim, cond_emb_dim, mlp_dim, multiplier=multiplier))
        self.lllite_modules = nn.ModuleList(modules)

    @classmethod
    def from_state_dict(
        cls, state_dict: dict[str, torch.Tensor], metadata: dict[str, str] | None
    ) -> AnimaControlNetLLLite:
        """Build the adapter from a saved v2 named-key state dict.

        Hyperparams come from ``lllite.*`` metadata when present, with
        state-dict-shape fallbacks. ``inpaint_masked_input`` is metadata-only
        (not derivable from shapes; defaults to False).
        """
        meta = metadata or {}

        if any(k.startswith(_LEGACY_MODULES_PREFIX) for k in state_dict):
            raise ValueError(
                f"State dict appears to be in a legacy ControlNet-LLLite weight format (keys starting "
                f"with '{_LEGACY_MODULES_PREFIX}'). Only the v2 named-key format is supported."
            )

        module_names: set[str] = set()
        for key in state_dict:
            head, dot, _tail = key.partition(".")
            if dot and MODULE_NAME_PATTERN.match(head):
                module_names.add(head)
        if not module_names:
            raise ValueError("State dict contains no LLLite modules (no 'lllite_dit_blocks_*' keys).")

        def sort_key(name: str) -> tuple[int, int]:
            match = MODULE_NAME_PATTERN.match(name)
            assert match is not None
            return int(match.group(1)), _SUFFIX_ORDER.index(match.group(2))

        sorted_names = sorted(module_names, key=sort_key)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Re-export the checkpoint with a current version of the training script (v2 named keys).
  2. Write a one-time conversion script renaming legacy 'lllite_modules.<i>.' keys to 'lllite_dit_blocks_<n>_<suffix>.' using the original module ordering.
  3. Obtain a v2-format version of the model from its source.
  4. Pin/upgrade library versions so trainer and loader formats match.

Example fix

# before
controlnet = ControlNetLLLiteDiT.from_state_dict(torch.load("old.safetensors"), meta)
# after
sd = convert_legacy_lllite_state_dict(torch.load("old.safetensors"))  # rename lllite_modules.<i>.* -> named keys
controlnet = ControlNetLLLiteDiT.from_state_dict(sd, meta)
Defensive patterns

Strategy: validation

Validate before calling

LEGACY_PREFIX = "lllite_modules"
def reject_legacy_format(state_dict: dict) -> None:
    legacy = [k for k in state_dict if k.startswith(LEGACY_PREFIX)]
    if legacy:
        raise ValueError(
            f"legacy LLLite format detected ({len(legacy)} keys, e.g. '{legacy[0]}'); "
            "convert to v2 named-key format first"
        )

Type guard

def is_v2_lllite_state_dict(sd: dict) -> bool:
    keys = list(sd)
    return not any(k.startswith("lllite_modules") for k in keys) and any(
        k.split(".")[0].startswith("lllite_dit_blocks_") for k in keys
    )

Try / catch

try:
    cnet = ControlNetLLLiteDiT.from_state_dict(sd, metadata)
except ValueError as e:
    if "legacy" in str(e):
        sd = convert_legacy_lllite_state_dict(sd)
        cnet = ControlNetLLLiteDiT.from_state_dict(sd, metadata)
    else:
        raise

Prevention

When it happens

Trigger: Loading an old ControlNet-LLLite checkpoint saved with keys like 'lllite_modules.0.down.weight' instead of named keys like 'lllite_dit_blocks_0_down.down.weight'.

Common situations: Using checkpoints trained/saved with an earlier version of the training code, or downloading community models created before the v2 format was introduced.

Related errors


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