sgl-project/sglang · error · ValueError
Validate failed: S({S}) must be divisible by F({F}).
Error message
Validate failed: S({S}) must be divisible by F({F}). What it means
When scale/shift is 4D (B, F, 1, D) — per-frame modulation — the sequence length S must be divisible by the number of frames F, because each frame's modulation is broadcast over S/F tokens. validate_scale_shift enforces S % F == 0.
Source
Thrown at python/sglang/kernels/ops/diffusion/norm/scale_residual_norm_cutedsl.py:229
def validate_scale_shift(t: torch.Tensor, B: int, S: int, D: int):
if t.dtype not in (torch.float16, torch.bfloat16, torch.float32):
raise ValueError(f"Validate failed: unsupported dtype: {t.dtype}")
failed = False
if t.ndim == 1 and (t.shape[0] not in (1, D)):
failed = True
elif t.ndim == 2 and ((t.shape[0] not in (1, B)) or t.shape[1] != D):
failed = True
elif t.ndim == 3 and (
(t.shape[0] not in (1, B)) or (t.shape[1] not in (1, S) or t.shape[2] != D)
):
failed = True
elif t.ndim == 4:
F = t.shape[1]
if t.shape[0] != B or t.shape[2] != 1 or t.shape[3] != D:
failed = True
elif S % F != 0:
raise ValueError(f"Validate failed: S({S}) must be divisible by F({F}).")
if failed:
raise ValueError(f"Validate failed: unsupported tensor shape: {t.shape}.")
if t.stride()[-1] != 1:
raise ValueError("Validate failed: not contiguous on dim D.")
def validate_gate(t: Union[torch.Tensor, int], B: int, S: int, D: int):
if not isinstance(t, torch.Tensor):
return
validate_scale_shift(t, B, S, D)
@torch.library.custom_op("sglang::fused_norm_scale_shift", mutates_args=())
def fused_norm_scale_shift(
x: torch.Tensor,
weight: Optional[torch.Tensor],
bias: Optional[torch.Tensor],
scale: torch.Tensor,View on GitHub (pinned to 0132848349)
Solutions
- Make S a multiple of F: fix the token count/patchify config so frames map evenly onto tokens
- Verify F equals the frame count actually used to build the latent, not a stale value
- Reshape modulation to a supported 1D (D or 1) or 2D (1/B, D) form if per-frame modulation isn't needed
Example fix
# before: S=256 tokens but F=7 frames fused_norm_scale_shift(x, w, b, scale_4d, shift_4d, "rms") # after: fix patchify so tokens_per_frame * F == S, e.g. S=256, F=8 assert S % F == 0
Defensive patterns
Strategy: validation
Validate before calling
if scale.ndim == 4:
F = scale.shape[1]
assert S % F == 0, f"S={S} not divisible by F={F}" Prevention
- Keep frame count and per-frame token count consistent through patchify changes
- Add an assert where latents are built linking S and F
When it happens
Trigger: Passing a 4D scale/shift with t.shape == (B, F, 1, D) where F does not divide the activation sequence length S (e.g. S=100, F=7).
Common situations: Video diffusion where img token count doesn't evenly match the number of latent frames after a patchify/tokenization change (e.g. patch size or token merge changed S without updating F).
Related errors
- Validate failed: unsupported tensor shape: {t.shape}.
- kv-canary: {name} must be 1-D, got shape {tuple(tensor.shape
- kv-canary: {name} must be 2-D, got shape {tuple(tensor.shape
- chunk_size should be a int, or a tuple of length 2 or 3, now
- Got {config.rope_axes_dim} but expected positional dim {pe_d
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/52862f75a441071c.
Report an issue: GitHub.