sgl-project/sglang · error · ValueError

[pred_noise_to_pred_video] Invalid timestep shape: {timestep

Error message

[pred_noise_to_pred_video] Invalid timestep shape: {timestep.shape}

What it means

pred_noise_to_pred_video validates that the timestep tensor is 0-D (scalar) or 1-D; anything else (2-D, 3-D, ...) raises this error. The scheduler needs a scalar or per-sample timestep to align with the noise_input_latent batch dimension for x0 prediction in diffusion sampling. A wrong-rank timestep almost always means the caller passed an un-squeezed or batched-padded tensor.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/diffusion_scheduler_utils.py:67


def pred_noise_to_pred_video(
    pred_noise: torch.Tensor,
    noise_input_latent: torch.Tensor,
    timestep: torch.Tensor,
    scheduler: Any,
) -> torch.Tensor:
    """Convert predicted noise to clean latent."""
    if timestep.ndim == 2:
        timestep = timestep.flatten(0, 1)
        assert timestep.numel() == noise_input_latent.shape[0]
    elif timestep.ndim == 1:
        if timestep.shape[0] == 1:
            timestep = timestep.expand(noise_input_latent.shape[0])
        else:
            assert timestep.numel() == noise_input_latent.shape[0]
    else:
        raise ValueError(
            f"[pred_noise_to_pred_video] Invalid timestep shape: {timestep.shape}"
        )

    dtype = pred_noise.dtype
    device = pred_noise.device
    pred_noise = pred_noise.double().to(device)
    noise_input_latent = noise_input_latent.double().to(device)
    sigmas = scheduler.sigmas.double().to(device)
    high_dtype = (
        torch.float64 if current_platform.is_float64_supported() else torch.float32
    )
    timesteps = scheduler.timesteps.to(high_dtype).to(device)
    timestep_id = torch.argmin(
        (timesteps.unsqueeze(0) - timestep.unsqueeze(1)).abs(), dim=1
    )
    sigma_t = sigmas[timestep_id].reshape(-1, 1, 1, 1)
    pred_video = noise_input_latent - sigma_t * pred_noise
    return pred_video.to(dtype)

View on GitHub (pinned to 0132848349)

Solutions

  1. Squeeze the timestep to a scalar or 1-D tensor: timestep.reshape(-1) or timestep.squeeze() before calling
  2. Pass a scalar (0-D) tensor when the whole batch shares a timestep
  3. Verify len(timestep) == noise_input_latent.shape[0] for the 1-D case

Example fix

# before
pred = scheduler.pred_noise_to_pred_video(t, model_out, noise_latent)  # t.shape == (B,1)
# after
t = t.reshape(-1) if t.ndim == 2 and t.shape[1] == 1 else t
pred = scheduler.pred_noise_to_pred_video(t, model_out, noise_latent)
Defensive patterns

Strategy: validation

Validate before calling

assert timestep.ndim <= 1, f"timestep must be 0/1-D, got {tuple(timestep.shape)}"
if timestep.ndim == 1 and timestep.shape[0] == 1:
    timestep = timestep.expand(noise_latent.shape[0])
out = scheduler.pred_noise_to_pred_video(timestep, pred_noise, noise_latent)

Type guard

def is_valid_timestep(t: torch.Tensor, batch: int) -> bool:
    return t.ndim == 0 or (t.ndim == 1 and t.numel() in (1, batch))

Prevention

When it happens

Trigger: Calling the scheduler's forward (or _predict_x0_btchw) with timestep of ndim >= 2, or a 1-D tensor whose length mismatches noise_input_latent.shape[0] (that path asserts instead). E.g. passing timestep.reshape(B,1) or a (B,1,1) tensor from a training-style code path.

Common situations: Porting training-loop code (which often uses (B,1) timesteps) into the inference scheduler; passing timesteps from a different diffusion library (diffusers uses (B,) or scalar); shape drift after batching refactor.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/f839df0ac9bb9ac2. Report an issue: GitHub.