xai-org/grok-1 · error · ValueError

Mask dimensionality {mask.ndim} must match logits dimensiona

Error message

Mask dimensionality {mask.ndim} must match logits dimensionality {attn_logits.ndim} for {mask.shape}/{attn_logits.shape}.

What it means

Raised in Grok-1's attention (model.py:871) when the boolean attention mask's rank does not equal the rank of attn_logits after the mask has been expanded with mask[:, :, None, :, :]. The einsum '...thHd,...Thd->...hHtT' produces 5-d logits [batch, seq', heads_per_group(window/shard), group, seq], so after the None insertion the mask must also be 5-d ([batch, seq', seq, ...]-compatible). This check is the library telling you the mask you injected via the hk.multi_transform or by patching _attention does not have the layout the kernel expects.

Source

Thrown at model.py:871

        query_heads = jnp.reshape(query_heads, (b, t, kv_h, h // kv_h, d))
        query_heads = with_sharding_constraint(
            query_heads, P(self.data_axis, None, "model", None, None)
        )

        # Compute attention weights.
        # Attention softmax is always carried out in fp32.
        attn_logits = jnp.einsum("...thHd,...Thd->...hHtT", query_heads, key_heads).astype(
            jnp.float32
        )
        attn_logits *= self.attn_output_multiplier
        max_attn_val = jnp.array(30.0, dtype=attn_logits.dtype)
        attn_logits = max_attn_val * jnp.tanh(attn_logits / max_attn_val)

        mask = mask[:, :, None, :, :]

        if mask is not None:
            if mask.ndim != attn_logits.ndim:
                raise ValueError(
                    f"Mask dimensionality {mask.ndim} must match logits dimensionality "
                    f"{attn_logits.ndim} for {mask.shape}/{attn_logits.shape}."
                )
            attn_logits = jnp.where(mask, attn_logits, -1e30)
        attn_weights = jax.nn.softmax(attn_logits).astype(query.dtype)  # [H, T', T]

        # Weight the values by the attention and flatten the head vectors.
        attn = jnp.einsum("...hHtT,...Thd->...thHd", attn_weights, value_heads)
        attn = with_sharding_constraint(attn, P(self.data_axis, None, "model", None, None))
        leading_dims = attn.shape[:2]
        attn = jnp.reshape(attn, (*leading_dims, -1))  # [T', H*V]
        attn = with_sharding_constraint(attn, P(self.data_axis, None, "model"))
        # Apply another projection to get the final embeddings.
        final_projection = Linear(
            self.model_size,
            with_bias=False,
            sharding=P("model", "data"),
            mesh=mesh,

View on GitHub (pinned to 7050ed204b)

Solutions

  1. Construct the mask with the repo's own helper: causal_mask = make_attention_mask(logits=..., scores=jnp.zeros([1, 1, 1, 1, 1])) or reuse exactly the mask shape built inside model.py's attention, so ranks stay in sync.
  2. If building manually, produce a 4-d mask of shape [batch, q_len, kv_len, 1] (or matching [B, T', T, G] pattern); the code's [:, :, None, :, :] then yields the required 5-d [B, T', 1, G, T]. Concretely: mask = mask[:, None, None, :, :] style bookkeeping — print mask.ndim and attn_logits.ndim side by side until equal.
  3. Diff your local model.py against the upstream xai-org/grok-1 model.py (git diff model.py) to catch stale mask plumbing from an older revision.
  4. Never pass None here despite the `if mask is not None` guard — the indexing above it raises first; use an all-True mask of the correct shape instead.

Example fix

# before: [B, T, T] causal mask (3-d) -> after expand 4-d != 5-d logits
mask = jnp.tril(jnp.ones((B, T, T), dtype=bool))

# after: add the group axis so the expand makes it 5-d
mask = jnp.tril(jnp.ones((B, T, T), dtype=bool))[:, :, None, :]   # [B, T, 1, T, 1]
# code's mask[:, :, None, :, :] then gives 5-d, matching [..., h, H, t, T] logits
Defensive patterns

Strategy: validation

Validate before calling

import jax.numpy as jnp

LOGITS_NDIM = 5  # [..., t(h-group), H, t', T] from '...thHd,...Thd->...hHtT'

def check_attention_mask(mask: jax.Array) -> jax.Array:
    if mask is None:
        raise TypeError('mask=None is unsupported: indexing runs before the None check')
    # model.py inserts one axis via mask[:, :, None, :, :], so pre-expand rank must be 4
    if mask.ndim + 1 != LOGITS_NDIM:
        mask = mask.reshape(mask.shape[0], mask.shape[-2], 1, mask.shape[-1], 1)  # adapt as needed
    assert mask.ndim + 1 == LOGITS_NDIM, f'mask ndim {mask.ndim} vs logits ndim {LOGITS_NDIM}'
    return mask

Type guard

def mask_rank_ok(mask: jax.Array) -> bool:
    """Mask is 4-d so the built-in axis expansion yields 5-d, matching logits."""
    return mask is not None and mask.ndim == 4

Try / catch

try:
    out = model.apply(params, tokens, mask=mask)
except ValueError as e:
    if 'Mask dimensionality' in str(e):
        mask = mask[:, None, :, :] if mask.ndim == 4 else mask[:, :, None, :, :]
        # only retry once with corrected rank; re-raise if still failing
        out = model.apply(params, tokens, mask=mask)
    else:
        raise

Prevention

When it happens

Trigger: Building your own attention mask and passing it into the model path that reaches this block: a plain [batch, seq, seq] (3-d) causal mask — after [:, :, None, :, :] it becomes 4-d while logits are 5-d; a 4-d mask intended 'as-is' (the code inserts the axis for you); or code from an older Grok-1 revision where make_attention_mask returned a different rank being reused with this revision. Note also the latent bug in this region: mask[:, :, None, :, :] runs BEFORE the `if mask is not None` check, so passing None crashes earlier with a TypeError.

Common situations: Adding bidirectional/padding masks for fine-tuning and assuming a [B, T, T] or [B, H, T, T] mask like BERT/PyTorch; porting masks between the two attention implementations in this repo (full vs sliding-window shard_map path have different expected ranks); upgrading the xai-org/grok-1 checkout and carrying a local _attention patch forward without re-checking rank.

Related errors


AI-assisted analysis of xai-org/grok-1@7050ed204b (2026-08-15). Data as JSON: /api/errors/4a51bc3f3731815c. Report an issue: GitHub.