{"record":{"id":"7b0764da31c7e8c1","repo":"sgl-project/sglang","slug":"scheduler-not-initialized-call-set-timesteps-fi","errorCode":null,"errorMessage":"Scheduler not initialized; call set_timesteps() first","messagePattern":"Scheduler not initialized; call set_timesteps\\(\\) first","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py","lineNumber":224,"sourceCode":"    def set_pair_postprocess(self, fn):\n        \"\"\"Set a postprocess function to customize pairs after construction.\n\n        Args:\n            fn: Callable with signature fn(pairs: torch.Tensor) -> torch.Tensor.\n                The returned tensor must have the same shape as input pairs.\n\n        Raises:\n            TypeError: If fn is not callable or None.\n            RuntimeError: If scheduler is not initialized.\n        \"\"\"\n        if fn is not None and not callable(fn):\n            raise TypeError(\"pair_postprocess must be callable or None\")\n        self._pair_postprocess_fn = fn\n        self._pair_postprocess_requires_source = (\n            False if fn is None else bool(getattr(fn, \"_requires_source\", False))\n        )\n        if self.timesteps is None or self.sigmas is None:\n            raise RuntimeError(\"Scheduler not initialized; call set_timesteps() first\")\n        self._refresh_pair_cache()\n\n    def set_pair_postprocess_by_name(self, name: str | None, **kwargs):\n        \"\"\"Configure a postprocess function by name.\n\n        Supported names:\n            - None/\"none\"/\"off\"/\"false\"/\"no\": disable\n            - \"quadratic_perp_bulge_swap\": x2=x+d, y2=x-d, where d=4*amp*s*(1-s), s=t/T\n            - \"v2a_sequential\": assume pairs are (t,t); sample half sequence from column 0\n              with stride 2, then let column 0 follow this sequence first, followed by column 1\n            - \"a2v_sequential\": same as above, but column 1 first then column 0\n            - \"dual_sigma_shift\": use only timestep count; rebuild two columns independently using\n              FlowMatchScheduler sigma transform logic; configurable visual_shift/audio_shift\n\n        Args:\n            name: Postprocess name or None to disable.\n            **kwargs: Extra parameters for the named postprocess. For example:\n                - amp: Float amplitude, default 150.0.","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py#L206-L242","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call scheduler.set_timesteps(num_inference_steps, ...) before set_pair_postprocess*","Reorder pipeline init: construct -> set_timesteps -> configure postprocess -> sample","If reusing across generations, re-run set_timesteps before swapping postprocess functions","Guard with a check: if scheduler.timesteps is None: initialize first"],"exampleFix":"// before\nsched = FlowMatchEulerPairScheduler(...)\nsched.set_pair_postprocess(fn)  # RuntimeError\n// after\nsched = FlowMatchEulerPairScheduler(...)\nsched.set_timesteps(num_inference_steps=50)\nsched.set_pair_postprocess(fn)","handlingStrategy":"validation","validationCode":"if scheduler.timesteps is None or scheduler.sigmas is None:\n    scheduler.set_timesteps(num_inference_steps=steps)\nscheduler.set_pair_postprocess(fn)","typeGuard":"def scheduler_ready(sched) -> bool:\n    return sched.timesteps is not None and sched.sigmas is not None","tryCatchPattern":"try:\n    sched.set_pair_postprocess(fn)\nexcept RuntimeError as e:\n    if 'set_timesteps' in str(e):\n        sched.set_timesteps(num_inference_steps=steps)\n        sched.set_pair_postprocess(fn)\n    else:\n        raise","preventionTips":["Fix init order: construct -> set_timesteps -> configure postprocess","Re-run set_timesteps when reusing a scheduler across generations","Encapsulate the full init sequence in a pipeline helper so callers cannot misorder it"],"tags":["scheduler","initialization-order","flow-match","state-error"],"backgroundTag":"uninitialized-component-use","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}