invoke-ai/InvokeAI · critical · RuntimeError

{what}: source keys {source_of.get(key)!r} and {source!r} bo

Error message

{what}: source keys {source_of.get(key)!r} and {source!r} both normalize to {key!r}. The checkpoint appears to mix native and target key layouts; refusing to silently drop one of the tensors.

What it means

When converting Krea-2 native (or Qwen3VL single-file) keys to diffusers layout, _put_unique_key normalizes each source key to a target key and detects collisions. A collision means the checkpoint carries BOTH a native-layout tensor and an already-converted diffusers tensor that normalize to the same target — a mixed-layout, malformed checkpoint. Since silently overwriting would make the result depend on dict iteration order, it refuses with a message naming both source keys.

Source

Thrown at invokeai/backend/model_manager/load/model_loaders/krea2.py:80

    if hasattr(value, "get_dequantized_tensor"):
        return value.get_dequantized_tensor()
    return value


def _put_unique_key(
    dest: dict[Any, Any], key: Any, value: Any, *, source: Any, source_of: dict[Any, Any], what: str
) -> None:
    """Assign ``dest[key] = value``, rejecting a collision produced by a different source key.

    These key normalizers map each source key to exactly one target key. A well-formed checkpoint is
    either fully native or already in the target layout, so two distinct source keys never collapse to
    the same target. A malformed *mixed-layout* checkpoint can, though — e.g. it carries both a native
    ``blocks.0.attn.wq.weight`` and an already-diffusers ``transformer_blocks.0.attn.to_q.weight`` that
    normalize to the same key. Silently overwriting would make the surviving tensor depend on dict
    iteration order, so reject with an actionable message instead of dropping one tensor.
    """
    if key in dest:
        raise RuntimeError(
            f"{what}: source keys {source_of.get(key)!r} and {source!r} both normalize to {key!r}. "
            "The checkpoint appears to mix native and target key layouts; refusing to silently drop "
            "one of the tensors."
        )
    dest[key] = value
    source_of[key] = source


def _is_native_krea2_format(sd: dict[str, Any]) -> bool:
    """Detect the native/ComfyUI Krea-2 key naming (e.g. GGUF) vs. the diffusers naming."""
    return any(
        isinstance(k, str) and (k.startswith(("blocks.", "txtfusion.", "first.")) or ".mod.lin" in k) for k in sd
    )


def _dequantize_scaled_fp8(sd: dict[str, Any], dtype: "torch.dtype") -> dict[str, Any]:
    """Dequantize ComfyUI 'scaled fp8' weights: ``dequant = weight.float() * weight_scale``.

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Inspect the checkpoint keys; delete the duplicated tensors belonging to the wrong layout, keeping one consistent layout.
  2. Re-download the checkpoint from the original source — the file is contaminated and untrustworthy.
  3. If merging is intentional, split into separate layout-pure files and convert each independently.
  4. Add an explicit key-preference policy (e.g. always prefer native layout) only if you can verify tensor equivalence.

Example fix

// before: checkpoint contains both
// blocks.0.attn.wq.weight and transformer_blocks.0.attn.to_q.weight
// after: strip native duplicates before loading
sd = {k: v for k, v in sd.items() if not k.startswith("blocks.")}
Defensive patterns

Strategy: validation

Validate before calling

import re
NATIVE = re.compile(r"^blocks\.\d+\.")
DIFFUSERS = re.compile(r"^transformer_blocks\.\d+\.")
if any(NATIVE.match(k) for k in sd) and any(DIFFUSERS.match(k) for k in sd):
    raise ValueError("checkpoint mixes native and diffusers key layouts")

Type guard

def is_layout_pure(sd: dict) -> bool:
    native = any(k.startswith("blocks.") for k in sd)
    diffusers = any(k.startswith("transformer_blocks.") for k in sd)
    return not (native and diffusers)

Try / catch

try:
    model = loader._load_model(cfg, SubModelType.Transformer)
except RuntimeError as e:
    if "both normalize to" in str(e):
        sd = strip_inconsistent_layout(sd)  # or re-download
    else:
        raise

Prevention

When it happens

Trigger: Running _convert_krea2_native_to_diffusers or _remap_qwen3vl_singlefile_keys on a checkpoint where e.g. both 'blocks.0.attn.wq.weight' and 'transformer_blocks.0.attn.to_q.weight' exist and normalize to the same target key.

Common situations: Merged checkpoints built by concatenating files from different layouts; partially converted checkpoints re-saved over the original; community uploads that mixed original and converted tensors.

Related errors


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