Tag: Shapes

  • ComfyUI mat1 and mat2 shapes cannot be multiplied: Fix the CLIP, VAE, and Checkpoint Mismatch (2026 Guide)

    What the Error Actually Means

    In PyTorch, RuntimeError: mat1 and mat2 shapes cannot be multiplied (77x2048 and 4096x3072) is thrown by a matrix-multiply operation (torch.matmul) when the inner dimensions do not line up. The two tuples in parentheses are the shapes of the two tensors being multiplied. The rule is simple: the second number of mat1 must equal the first number of mat2. In the example above, 2048 does not equal 4096, so the operation is impossible.

    When you see this inside ComfyUI, it almost never means your GPU is broken or your install is corrupt. It means a model component expects an embedding space (a vector width) that a different component is not producing. The most common culprits are a mis-matched text encoder (CLIP), a mis-matched VAE, or a checkpoint that does not belong to the same architecture family as the other pieces in your graph.

    Think of it as three puzzle pieces — the checkpoint (UNet), the CLIP text encoder(s), and the VAE — that all have to come from the same generation of models. SD1.5, SD2.x, SDXL, and FLUX each use different embedding widths internally. Mixing a piece from one family with a piece from another produces exactly this shape error, because the tensors flowing between nodes have incompatible widths.

    Read the Traceback Before You Change Anything

    Before touching a single node, read the full error text in the ComfyUI terminal window. The two shape tuples tell you most of what you need to know, and the traceback tells you which node blew up.

    • Where it happened: the traceback starts inside comfy/sd.py or a sampling/custom-node file. Look at the last few frames for a node name such as CLIPTextEncode, VAEDecode, KSampler, or a custom node like CLIPTextEncodeSDXL.
    • The widths: note the second number of mat1 and the first number of mat2. Common mismatches map to known families:
      • ...x768 vs ...x1024 → SD1.5 vs SDXL (or vice-versa)
      • ...x2048 vs ...x1024 or 3072 → SD2.x vs SDXL
      • Very large widths like 1024 / 1280 / 4096 appearing in CLIP errors → FLUX or a GGUF clip variant

    The single most reliable diagnostic step is to isolate which component is on the wrong side. If the error fires in a CLIPTextEncode node, it is a text-encoder mismatch. If it fires in a VAEDecode or VAEEncode node, it is a VAE mismatch. If it fires deep inside the KSampler/model load, it is a checkpoint mismatch. This one observation usually narrows a vague “shapes” error down to a specific node in under a minute.

    The Three-Mismatch Checklist

    1. CLIP / text encoder mismatch

    This is the most frequent cause. A checkpoint has a fixed text-encoder architecture baked in. Loading an SDXL checkpoint while keeping an SD1.5 CLIP model in the graph (or vice-versa) produces a width mismatch at the CLIPTextEncode step. SDXL uses two CLIP encoders (CLIP_L and CLIP_G, often split across two files or referenced through a dedicated CLIPTextEncodeSDXL node), while SD1.5 uses a single clip_l model. If your workflow (see ComfyUI workflow.json vs API format) has a CLIPTextEncode (singular) node feeding an SDXL checkpoint, that is a red flag immediately.

    • Confirm the checkpoint family first (SD1.5 / SD2.x / SDXL / FLUX / SD3).
    • Load the matching CLIP model(s) into the text-encoder loader (see ComfyUI model directory errors) node.
    • For SDXL, use the SDXL encode node and both encoders; a single-encoder node will generally not produce the correct double-conditioning widths.

    2. VAE mismatch

    VAEs also have fixed latent channel widths. An SD1.5 VAE (4 latent channels) versus SDXL or FLUX VAE is a classic source of a shape error at the decode/encode boundary. The symptom is usually a clean run up until the final image decode, then a crash with mismatched latent tensors.

    • Load the VAE that ships with (or is documented for) your checkpoint family.
    • If you are using a bundled/merged checkpoint, its internal VAE is usually correct — adding an external, mismatched VAE node on top is what breaks it.

    3. Checkpoint / model architecture mismatch

    This happens when a workflow was built for one model generation and a checkpoint from another was dropped in without updating the rest of the graph. The safest fix is to re-verify all three components come from one family. When in doubt, start from the model’s official example workflow (the ComfyUI examples repository is the canonical source) rather than re-wiring an old graph by hand.

    Reproduce, Then Isolate

    To reproduce and confirm the diagnosis deterministically, do the smallest possible change first:

    1. Note the exact node where the error fires (from the traceback).
    2. Replace only that node’s component with the correct one for the checkpoint family, leaving everything else untouched.
    3. Re-run. If the error moves to a different node, you have a second mismatch — repeat the process.
    4. If the error persists at the same node with the same widths, the component may be a quantized variant (e.g., a GGUF clip) whose metadata does not match your loader node; switch to the fp8/fp16 version the loader expects.

    A subtle but common pitfall is a GGUF CLIP model. Several GGUF clip quantizations produce different internal widths than their safetensors counterparts, and a loader node compiled for one format will throw this exact error when handed the other. If you mixed GGUF and non-GGUF text encoders across the workflow, standardize on one format and re-test.

    Another pitfall is rerouted conditioning: if a custom node preprocesses or concatenates CLIP embeddings before KSampler, a width change upstream (for example, swapping to SDXL CLIP) can break a hard-coded tensor assumption downstream. Check any custom node sitting between CLIPTextEncode and KSampler that does not exist in the official example graph.

    Verifying the Fix

    After correcting the mismatched component, confirm the fix with a clean run, not just an absence of the error message:

    • The same prompt should now produce a valid image (or latent) with no warnings about dropped dimensions.
    • Check the ComfyUI terminal for any lingering UserWarning about mismatched tensor sizes that did not halt execution — these can silently degrade output.
    • If you changed the text encoder, verify conditioning output with the prompt’s original intended width (SDXL conditions at one width, SD1.5 at another); a prompt that “works” but produces washed-out or blurry output often still has a latent-size mismatch further down the graph.

    For a broader mental model of how these components interact inside a local generation pipeline, see our write-up on the open-source video generation stack, which walks through the same checkpoint/CLIP/VAE tripling for video models. And for the motion-model side of the same architecture question, our piece on Wan2.2-Animate covers how the encoder components differ across the Wan family.

    Conclusion

    A mat1 and mat2 shapes cannot be multiplied error in ComfyUI is a dimension-mismatch signal, not a hardware fault. In nearly every case it traces back to one of three mis-matched pieces — the CLIP text encoder, the VAE, or the checkpoint — being pulled from a different model family than the rest of the graph. Read the traceback to identify the failing node, compare the two shape tuples against the known architecture widths, then correct that single component and re-run. Isolating the mismatch before touching any other node is what turns a cryptic PyTorch error into a two-minute fix.

    For the canonical component layout and model file placement, refer to the official ComfyUI examples documentation, and check the ComfyUI repository for the current node implementations that define each model family’s expected tensor widths.