hpcaitech/Open-Sora · error · ValueError
The last dimension D must be even.
Error message
The last dimension D must be even.
What it means
rearrange_tensor interleaves a 4D [B, H, L, D] tensor's head dimension by splitting D into two halves and shuffling even/odd indices (Rearrange '... (s d) -> ... d s' style used before interleaved QKV projection packing). This permutation only exists when D is even, so an odd last dimension raises immediately.
Source
Thrown at opensora/models/mmdit/math.py:81
xq_out = freqs_cis[..., 0] * xq_[..., 0] + freqs_cis[..., 1] * xq_[..., 1]
xk_out = freqs_cis[..., 0] * xk_[..., 0] + freqs_cis[..., 1] * xk_[..., 1]
return xq_out.reshape(*xq.shape).type_as(xq), xk_out.reshape(*xk.shape).type_as(xk)
def rearrange_tensor(tensor):
"""
Rearranges the last dimension (D) of the input tensor based on the specified mapping:
2d -> d, 2d+1 -> D/2 + d.
Args:
tensor (torch.Tensor): Input tensor of shape [B, H, L, D], where D is even.
Returns:
torch.Tensor: Tensor with rearranged last dimension, same shape as input.
"""
B, H, L, D = tensor.shape
if D % 2 != 0:
raise ValueError("The last dimension D must be even.")
half_D = D // 2
indices = torch.empty(D, dtype=torch.long, device=tensor.device)
# Fill the indices based on the mapping rule
indices[:half_D] = torch.arange(0, D, 2, device=tensor.device)
indices[half_D:] = torch.arange(1, D, 2, device=tensor.device)
# Rearrange the tensor based on the computed indices
return tensor.index_select(dim=-1, index=indices)
def reverse_rearrange_tensor(tensor):
"""
Restores the original order of the last dimension (D) of the input tensor based on the reverse mapping:
d -> 2d, D/2 + d -> 2d + 1.
Args:View on GitHub (pinned to 7ad6a96a13)
Solutions
- Check tensor.shape[-1] % 2 == 0 before calling; if odd, your upstream projection or reshape is wrong
- Verify num_heads divides hidden_size and the per-head dimension layout matches what rearrange_tensor expects
- Use the matching reverse_rearrange_tensor after the operation to round-trip correctly
Example fix
# before
y = rearrange_tensor(x) # x.shape[-1] == 375
# after
assert x.shape[-1] % 2 == 0, f"odd head dim {x.shape[-1]}"
y = rearrange_tensor(x) Defensive patterns
Strategy: validation
Validate before calling
assert tensor.dim() == 4 and tensor.shape[-1] % 2 == 0, f"need even last dim, got {tensor.shape}" Type guard
def has_even_head_dim(t: torch.Tensor) -> bool:
return t.dim() == 4 and t.shape[-1] % 2 == 0 Prevention
- Assert even head dims in attention weight-loading utilities
- Keep num_heads * 2-compatible head dims in configs
- Round-trip test rearrange/reverse_rearrange on your shapes
When it happens
Trigger: Calling rearrange_tensor(tensor) where tensor.shape[-1] is odd — e.g. a projection output of size 3*head_dim per-head being fed with an incompatible head packing, or a custom attention head_dim producing an odd D.
Common situations: Changing num_heads/hidden_size so that per-head dim becomes odd; feeding attention weights that were packed for interleaved layouts into a tensor whose last dim is not 2-divisible.
Related errors
- Unsupported input dimension: {x.dim()}
- No chunks were generated. Input shape: {x.shape}
- Hidden size {config.hidden_size} must be divisible by num_he
- Input img and txt tensors must have 3 dimensions.
- Activation buffer is full
AI-assisted analysis of hpcaitech/Open-Sora@7ad6a96a13 (2026-08-28).
Data as JSON: /api/errors/763858a357bf825e.
Report an issue: GitHub.