sgl-project/sglang · error · ValueError

num_inference_steps must be positive, got {steps}

Error message

num_inference_steps must be positive, got {steps}

What it means

LTX-2's prepare_sigmas builds the sigma schedule [1 - i/steps] when no explicit sigmas are passed; a non-positive num_inference_steps (0 or negative) would produce an empty/invalid schedule, so it is rejected up front.

Source

Thrown at python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py:262

    # two logical encoders sharing the same underlying `text_encoder` module.
    text_encoder_configs: tuple[EncoderConfig, ...] = field(
        default_factory=lambda: (Gemma3Config(),)
    )
    text_encoder_precisions: tuple[str, ...] = field(default_factory=lambda: ("bf16",))
    text_encoder_extra_args: list[dict] = field(default_factory=lambda: [{}])

    preprocess_text_funcs: tuple[Callable[[str], str] | None, ...] = field(
        default_factory=lambda: (None,)
    )
    postprocess_text_funcs: tuple[
        Callable[[BaseEncoderOutput, dict], torch.Tensor], ...
    ] = field(default_factory=lambda: (_gemma_postprocess_func,))

    def prepare_sigmas(self, sigmas, num_inference_steps):
        if sigmas is None:
            steps = int(num_inference_steps)
            if steps <= 0:
                raise ValueError(f"num_inference_steps must be positive, got {steps}")
            return [1.0 - i / steps for i in range(steps)]
        return sigmas

    def tokenize_prompt(self, prompt: list[str], tokenizer, tok_kwargs) -> dict:
        # Adapted from diffusers_pipeline.py _get_gemma_prompt_embeds
        # But we only need tokenization here, the embedding happens in TextEncodingStage
        # Official LTX Gemma tokenizer trims surrounding whitespace before
        # tokenization.
        prompt = [text.strip() for text in prompt]

        # Gemma expects left padding for chat-style prompts
        tokenizer.padding_side = "left"
        if tokenizer.pad_token is None:
            tokenizer.pad_token = tokenizer.eos_token

        max_sequence_length = tok_kwargs.get(
            "max_length", 1024
        )  # Default from diffusers pipeline

View on GitHub (pinned to 0132848349)

Solutions

  1. Set num_inference_steps to a positive integer (typically 20-50 for LTX-2)
  2. If computing steps from strength, clamp: max(1, int(strength * total_steps))
  3. Pass an explicit sigmas list if you want to bypass step-count schedule generation
  4. Validate request params before submission

Example fix

# before
steps = int(strength * num_inference_steps)  # 0 when strength small
out = pipe(prompt, num_inference_steps=steps)

# after
steps = max(1, int(strength * num_inference_steps))
out = pipe(prompt, num_inference_steps=steps)
Defensive patterns

Strategy: validation

Validate before calling

num_inference_steps = max(1, int(num_inference_steps))
assert num_inference_steps > 0

Try / catch

except ValueError as e:
    if "num_inference_steps must be positive" in str(e):
        pipe(prompt, num_inference_steps=30)  # sane default retry

Prevention

When it happens

Trigger: Calling generation with sigmas=None and num_inference_steps <= 0 — e.g. 0, -1, or a value that int() truncates to 0 (like 0.5).

Common situations: num_inference_steps read from a config/CLI where the default was never set (0), computed as steps = strength * total and rounding to 0 at low strength, or a typo/negative value in request parameters.

Related errors


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