sgl-project/sglang · error · TypeError
pair_postprocess must be callable or None
Error message
pair_postprocess must be callable or None
What it means
FlowMatchEulerPairScheduler.set_pair_postprocess accepts only a callable (the postprocess applied to sampler outputs each step) or None to disable it. Passing anything else — a string name, a list of functions, a bound non-callable attribute — raises TypeError.
Source
Thrown at python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py:218
reverse_sigmas=reverse_sigmas,
exponential_shift=exponential_shift,
exponential_shift_mu=exponential_shift_mu,
shift_terminal=shift_terminal,
)
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 usingView on GitHub (pinned to 0132848349)
Solutions
- Pass the function object itself (or functools.partial(fn, **kwargs)) or None
- If you have a name string, call set_pair_postprocess_by_name(name, **kwargs) instead
- Ensure custom postprocess functions are plain callables taking the expected signature
Example fix
// before
sched.set_pair_postprocess('rescale_noise_sigma')
// after
sched.set_pair_postprocess_by_name('rescale_noise_sigma')
# or
from x import rescale_noise_sigma
sched.set_pair_postprocess(rescale_noise_sigma) Defensive patterns
Strategy: type-guard
Validate before calling
assert fn is None or callable(fn), f'pair_postprocess must be callable or None, got {type(fn)}' Type guard
def is_postprocess_arg(fn) -> bool:
return fn is None or callable(fn) Try / catch
try:
sched.set_pair_postprocess(fn)
except TypeError:
if isinstance(fn, str):
sched.set_pair_postprocess_by_name(fn)
else:
raise Prevention
- Use set_pair_postprocess_by_name for string configs
- Wrap fn + kwargs with functools.partial instead of tuples/dicts
- Type-annotate the parameter as Callable | None in your own wrappers
When it happens
Trigger: Calling scheduler.set_pair_postprocess(fn) where fn is e.g. a function name string like 'rescale_noise_sigma' instead of the function object, or a tuple of (fn, kwargs). Use set_pair_postprocess_by_name for string-based configuration.
Common situations: Config-driven code that passes the postprocess name straight through; serializing/deserializing a pipeline and losing the function reference; wrapping the fn in a dict for kwargs instead of using functools.partial.
Related errors
- Scheduler not initialized; call set_timesteps() first
- spt must be a bool when provided
- Unknown type: {type(other)}
- Invalid value: {other}
- Unsupported image type: {type(image)}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/e478f273c2cafd58.
Report an issue: GitHub.