sgl-project/sglang · error · ValueError

Only one of `timesteps` or `sigmas` can be passed. Please ch

Error message

Only one of `timesteps` or `sigmas` can be passed. Please choose one to set custom values

What it means

retrieve_timesteps (copied from diffusers) builds the denoising schedule and allows customizing it via either an explicit timesteps array or a sigmas array — but only one. Passing both is ambiguous, so it raises immediately.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/qwen_image_layered.py:125

            The scheduler to get timesteps from.
        num_inference_steps (`int`):
            The number of diffusion steps used when generating samples with a pre-trained model. If used, `timesteps`
            must be `None`.
        device (`str` or `torch.device`, *optional*):
            The device to which the timesteps should be moved to. If `None`, the timesteps are not moved.
        timesteps (`List[int]`, *optional*):
            Custom timesteps used to override the timestep spacing strategy of the scheduler. If `timesteps` is passed,
            `num_inference_steps` and `sigmas` must be `None`.
        sigmas (`List[float]`, *optional*):
            Custom sigmas used to override the timestep spacing strategy of the scheduler. If `sigmas` is passed,
            `num_inference_steps` and `timesteps` must be `None`.

    Returns:
        `Tuple[torch.Tensor, int]`: A tuple where the first element is the timestep schedule from the scheduler and the
        second element is the number of inference steps.
    """
    if timesteps is not None and sigmas is not None:
        raise ValueError(
            "Only one of `timesteps` or `sigmas` can be passed. Please choose one to set custom values"
        )
    if timesteps is not None:
        accepts_timesteps = "timesteps" in set(
            inspect.signature(scheduler.set_timesteps).parameters.keys()
        )
        if not accepts_timesteps:
            raise ValueError(
                f"The current scheduler class {scheduler.__class__}'s `set_timesteps` does not support custom"
                f" timestep schedules. Please check whether you are using the correct scheduler."
            )
        scheduler.set_timesteps(timesteps=timesteps, device=device, **kwargs)
        timesteps = scheduler.timesteps
        num_inference_steps = len(timesteps)
    elif sigmas is not None:
        accept_sigmas = "sigmas" in set(
            inspect.signature(scheduler.set_timesteps).parameters.keys()
        )

View on GitHub (pinned to 0132848349)

Solutions

  1. Delete one of the two arguments — keep whichever your scheduler actually consumes (flow-matching schedulers typically use sigmas; DDPM-style use timesteps).
  2. If merging config dicts, pop the unused key before the call.
  3. Prefer passing num_inference_steps alone unless you truly need a custom schedule.

Example fix

# before
stage(..., timesteps=[999, 750, 500], sigmas=[14.6, 5.0, 0.0])

# after
stage(..., sigmas=[14.6, 5.0, 0.0])
Defensive patterns

Strategy: validation

Validate before calling

assert not (timesteps is not None and sigmas is not None), "pass only one of timesteps/sigmas"

Type guard

def schedule_args_ok(timesteps, sigmas) -> bool:
    return not (timesteps is not None and sigmas is not None)

Prevention

When it happens

Trigger: Calling the pipeline/stage with both timesteps=... and sigmas=... keyword arguments in the same call (e.g. timesteps=[999, 500, 100] and sigmas=[14.6, 3.0, 0.0]).

Common situations: Copy-pasting example code that sets both when migrating from another scheduler API; building a config dict that merges defaults for both fields and splats **cfg into the call; upgrading diffusers-style code where old code set sigmas and new code added timesteps.

Related errors


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