sgl-project/sglang · error · RuntimeError

Scheduler not initialized; call set_timesteps() first

Error message

Scheduler not initialized; call set_timesteps() first

What it means

set_pair_postprocess refreshes a cached pairing structure (via _refresh_pair_cache) that depends on the computed timesteps/sigmas grid. If set_timesteps() has not been run yet, timesteps or sigmas is None and the scheduler refuses to build the cache, telling you to initialize first.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py:224

    def set_pair_postprocess(self, fn):
        """Set a postprocess function to customize pairs after construction.

        Args:
            fn: Callable with signature fn(pairs: torch.Tensor) -> torch.Tensor.
                The returned tensor must have the same shape as input pairs.

        Raises:
            TypeError: If fn is not callable or None.
            RuntimeError: If scheduler is not initialized.
        """
        if fn is not None and not callable(fn):
            raise TypeError("pair_postprocess must be callable or None")
        self._pair_postprocess_fn = fn
        self._pair_postprocess_requires_source = (
            False if fn is None else bool(getattr(fn, "_requires_source", False))
        )
        if self.timesteps is None or self.sigmas is None:
            raise RuntimeError("Scheduler not initialized; call set_timesteps() first")
        self._refresh_pair_cache()

    def set_pair_postprocess_by_name(self, name: str | None, **kwargs):
        """Configure a postprocess function by name.

        Supported names:
            - None/"none"/"off"/"false"/"no": disable
            - "quadratic_perp_bulge_swap": x2=x+d, y2=x-d, where d=4*amp*s*(1-s), s=t/T
            - "v2a_sequential": assume pairs are (t,t); sample half sequence from column 0
              with stride 2, then let column 0 follow this sequence first, followed by column 1
            - "a2v_sequential": same as above, but column 1 first then column 0
            - "dual_sigma_shift": use only timestep count; rebuild two columns independently using
              FlowMatchScheduler sigma transform logic; configurable visual_shift/audio_shift

        Args:
            name: Postprocess name or None to disable.
            **kwargs: Extra parameters for the named postprocess. For example:
                - amp: Float amplitude, default 150.0.

View on GitHub (pinned to 0132848349)

Solutions

  1. Call scheduler.set_timesteps(num_inference_steps, ...) before set_pair_postprocess*
  2. Reorder pipeline init: construct -> set_timesteps -> configure postprocess -> sample
  3. If reusing across generations, re-run set_timesteps before swapping postprocess functions
  4. Guard with a check: if scheduler.timesteps is None: initialize first

Example fix

// before
sched = FlowMatchEulerPairScheduler(...)
sched.set_pair_postprocess(fn)  # RuntimeError
// after
sched = FlowMatchEulerPairScheduler(...)
sched.set_timesteps(num_inference_steps=50)
sched.set_pair_postprocess(fn)
Defensive patterns

Strategy: validation

Validate before calling

if scheduler.timesteps is None or scheduler.sigmas is None:
    scheduler.set_timesteps(num_inference_steps=steps)
scheduler.set_pair_postprocess(fn)

Type guard

def scheduler_ready(sched) -> bool:
    return sched.timesteps is not None and sched.sigmas is not None

Try / catch

try:
    sched.set_pair_postprocess(fn)
except RuntimeError as e:
    if 'set_timesteps' in str(e):
        sched.set_timesteps(num_inference_steps=steps)
        sched.set_pair_postprocess(fn)
    else:
        raise

Prevention

When it happens

Trigger: Calling set_pair_postprocess / set_pair_postprocess_by_name on a freshly constructed FlowMatchEulerPairScheduler before any set_timesteps(num_inference_steps, ...) call, or after code that resets timesteps/sigmas to None.

Common situations: Pipeline init ordering: configuring postprocess in __init__ before the scheduler is prepared for a specific resolution/step count; reconfiguring between generations after tearing down timesteps; porting pipeline code that assumed lazy initialization.

Related errors


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