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
- Inspect the checkpoint keys; delete the duplicated tensors belonging to the wrong layout, keeping one consistent layout.
- Re-download the checkpoint from the original source — the file is contaminated and untrustworthy.
- If merging is intentional, split into separate layout-pure files and convert each independently.
- 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
- Checksum-verify checkpoints after download; reject files from unknown merge scripts.
- Scan checkpoint keys for mixed layout patterns before conversion.
- Keep a single canonical layout per checkpoint file.
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
- Unrecognized LLLite module name: '{name}'
- State dict appears to be in a legacy ControlNet-LLLite weigh
- State dict contains no LLLite modules (no 'lllite_dit_blocks
- LLLite module '{name}' is missing key '{down_key}'
- Unexpected key: {k}
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/0f0e445e655a7757.
Report an issue: GitHub.