{"record":{"id":"dbff742d70943da8","repo":"sgl-project/sglang","slug":"ideogram4denoisingstage-applies-its-custom-schedul","errorCode":null,"errorMessage":"Ideogram4DenoisingStage applies its custom scheduler step","messagePattern":"Ideogram4DenoisingStage applies its custom scheduler step","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/ideogram.py","lineNumber":116,"sourceCode":"        self._begin_index = None\n\n    def set_begin_index(self, begin_index: int) -> None:\n        self._begin_index = begin_index\n\n    def set_timesteps(self, num_inference_steps: int, device=None) -> None:\n        self.timesteps = torch.arange(\n            num_inference_steps - 1,\n            -1,\n            -1,\n            dtype=torch.float32,\n            device=device or get_local_torch_device(),\n        )\n\n    def scale_model_input(self, sample: torch.Tensor, timestep=None) -> torch.Tensor:\n        return sample\n\n    def step(self, model_output, timestep, sample, return_dict=False, **kwargs):\n        raise RuntimeError(\"Ideogram4DenoisingStage applies its custom scheduler step\")\n\n\nclass Ideogram4TextEncodingStage(TextEncodingStage):\n    deduplicated_extra_tensor_tree_output_keys = (\"ideogram4\",)\n\n    def __init__(self, text_encoder, tokenizer) -> None:\n        super().__init__([text_encoder], [tokenizer])\n\n    def _tokenize(self, prompt: str, max_text_tokens: int):\n        messages = [{\"role\": \"user\", \"content\": [{\"type\": \"text\", \"text\": prompt}]}]\n        text = self.tokenizers[0].apply_chat_template(\n            messages, add_generation_prompt=True, tokenize=False\n        )\n        encoded = self.tokenizers[0](\n            text, return_tensors=\"pt\", add_special_tokens=False\n        )\n        token_ids = encoded[\"input_ids\"][0]\n        num_text_tokens = int(token_ids.shape[0])","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/ideogram.py#L98-L134","documentation":"Ideogram4DenoisingStage ships its own custom denoising step implementation, so the stock scheduler API step() is intentionally disabled. Calling step() on this stage raises immediately — it exists only to satisfy the scheduler interface and signal misuse. The real step logic is applied inside the stage's forward/_denoise_* methods.","triggerScenarios":"Any code path that treats the stage like a standard diffusers SchedulerMixin and calls .step(model_output, timestep, sample), e.g. generic denoising-loop boilerplate reused across models, or third-party code iterating pipelines via the scheduler interface.","commonSituations":"Porting a generic diffusion sampling loop to Ideogram4D; a shared utility calling scheduler.step uniformly over all stages; version upgrade where the stage now subclasses a scheduler-like interface it previously did not.","solutions":["Do not call step() on Ideogram4DenoisingStage; let its forward()/custom denoise methods drive sampling","Refactor shared sampling utilities to dispatch on stage type or use the stage's documented denoising entry point","If you need custom stepping, implement it in the stage's _denoise_* hooks instead of calling step()"],"exampleFix":"# before\nfor t in timesteps:\n    noise = model(x, t)\n    x = ideogram_stage.step(noise, t, x).prev_sample\n\n# after\n# delegate to the stage's own denoising loop\nx = ideogram_stage.forward(batch, server_args)","handlingStrategy":"type-guard","validationCode":"from sglang.multimodal_gen.runtime.pipelines_core.stages.model_specific_stages.ideogram import Ideogram4DenoisingStage\nif isinstance(stage, Ideogram4DenoisingStage):\n    out = stage.forward(batch, server_args)  # custom loop\nelse:\n    x = stage.step(noise, t, x).prev_sample","typeGuard":"def uses_custom_step(stage) -> bool:\n    return isinstance(stage, Ideogram4DenoisingStage)","tryCatchPattern":"try:\n    x = stage.step(noise, t, x)\nexcept RuntimeError as e:\n    if \"custom scheduler step\" in str(e):\n        x = stage.forward(batch, server_args)\n    else:\n        raise","preventionTips":["Dispatch per-model in shared sampling loops instead of assuming the diffusers scheduler API","Read the stage's docs before reusing generic denoise boilerplate"],"tags":["ideogram","scheduler","unsupported-operation","diffusers"],"backgroundTag":"unsupported-api-invocation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}