Comfy-Org/ComfyUI · error · ValueError

Query heads must be divisible by key/value heads for GQA: {q

Error message

Query heads must be divisible by key/value heads for GQA: {query_heads} vs {key_heads}

What it means

For grouped-query attention the query head count must be an exact multiple of the key/value head count, otherwise K/V heads cannot be evenly repeated to match Q. gqa_repeat_factor raises when query_heads % key_heads != 0, after first checking K/V equality. Typical configs are 8Q/2KV or 32Q/8KV; anything non-divisible is a config or weight-layout error.

Source

Thrown at comfy/ops.py:46

import comfy.pinned_memory
import comfy.utils

import comfy_aimdo.model_vbar
import comfy_aimdo.torch

def run_every_op():
    if torch.compiler.is_compiling():
        return

    comfy.model_management.throw_exception_if_processing_interrupted()

def gqa_repeat_factor(query_heads, key_heads, value_heads):
    if key_heads != value_heads:
        raise ValueError(f"Key/value head count mismatch for GQA: {key_heads} != {value_heads}")
    if query_heads == key_heads:
        return 1
    if query_heads % key_heads != 0:
        raise ValueError(f"Query heads must be divisible by key/value heads for GQA: {query_heads} vs {key_heads}")
    return query_heads // key_heads

def repeat_kv_for_gqa(k, v, query_heads, head_dim):
    n_rep = gqa_repeat_factor(query_heads, k.shape[head_dim], v.shape[head_dim])
    if n_rep > 1:
        k = k.repeat_interleave(n_rep, dim=head_dim)
        v = v.repeat_interleave(n_rep, dim=head_dim)
    return k, v

def scaled_dot_product_attention(q, k, v, *args, **kwargs):
    attn_mask = args[0] if len(args) > 0 else kwargs.get("attn_mask")
    if kwargs.get("enable_gqa", False) and attn_mask is not None:
        k, v = repeat_kv_for_gqa(k, v, q.shape[-3], -3)
        kwargs["enable_gqa"] = False
    return torch.nn.functional.scaled_dot_product_attention(q, k, v, *args, **kwargs)


try:

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Make query_heads a multiple of the KV head count (e.g. 8/2, 16/4, 32/8).
  2. Verify the argument order — query_heads is the full query head count, not the group size.
  3. If the model genuinely uses MQA (1 KV head) ensure KV tensors actually have shape 1 on the head axis.

Example fix

# before
k, v = repeat_kv_for_gqa(k, v, query_heads=12, head_dim=2)  # kv heads = 8
# after
k, v = repeat_kv_for_gqa(k, v, query_heads=16, head_dim=2)  # 16 % 8 == 0
Defensive patterns

Strategy: validation

Validate before calling

kv_heads = k.shape[head_dim]
if q_heads % kv_heads != 0:
    raise ValueError(f"q_heads {q_heads} not divisible by kv_heads {kv_heads}; fix attention config")
n_rep = gqa_repeat_factor(q_heads, kv_heads, kv_heads)

Type guard

def is_valid_gqa(q_heads, kv_heads) -> bool:
    return q_heads % kv_heads == 0

Prevention

When it happens

Trigger: repeat_kv_for_gqa(k, v, query_heads=12, head_dim=...) with 8 KV heads; or passing the sequence length / head dim as query_heads by mistake.

Common situations: Custom attention configs with non-divisible head splits; passing num_kv_heads where query heads are expected; checkpoints with unusual GQA ratios that need a different attention path.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/7b5234165073ce2e. Report an issue: GitHub.