{"record":{"id":"c78ef43238621381","repo":"sgl-project/sglang","slug":"pairs-must-be-a-torch-tensor","errorCode":null,"errorMessage":"pairs must be a torch.Tensor","messagePattern":"pairs must be a torch\\.Tensor","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py","lineNumber":367,"sourceCode":"        if name == \"dual_sigma_shift\":\n            visual_shift = float(kwargs.get(\"visual_shift\", self.shift))\n            audio_shift = float(kwargs.get(\"audio_shift\", self.shift))\n            visual_denoising_strength = float(\n                kwargs.get(\"visual_denoising_strength\", 1.0)\n            )\n            audio_denoising_strength = float(\n                kwargs.get(\"audio_denoising_strength\", 1.0)\n            )\n            visual_mu = kwargs.get(\n                \"visual_exponential_shift_mu\", self.exponential_shift_mu\n            )\n            audio_mu = kwargs.get(\n                \"audio_exponential_shift_mu\", self.exponential_shift_mu\n            )\n\n            def _dual_sigma_shift(pairs: torch.Tensor, *, source: str):\n                if not isinstance(pairs, torch.Tensor):\n                    raise TypeError(\"pairs must be a torch.Tensor\")\n                if pairs.ndim != 2 or pairs.shape[1] != 2:\n                    raise ValueError(\"pairs must be a torch.Tensor of shape [N, 2]\")\n                if pairs.shape[0] == 0:\n                    raise ValueError(\"pairs length must be greater than 0\")\n                if source not in (\"timesteps\", \"sigmas\"):\n                    raise ValueError(\"source must be 'timesteps' or 'sigmas'\")\n\n                num_steps = pairs.shape[0]\n                device = pairs.device\n                dtype = pairs.dtype\n\n                def _build_column(\n                    shift_value: float, denoising_strength: float, mu_override\n                ):\n                    if shift_value <= 0:\n                        raise ValueError(\"shift must be positive\")\n                    if denoising_strength <= 0:\n                        raise ValueError(\"denoising_strength must be positive\")","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/models/schedulers/flow_match_pair.py#L349-L385","documentation":"The 'dual_sigma_shift' postprocess fully validates its input before rebuilding both modality columns with the FlowMatchScheduler sigma transform. Its first check is a TypeError raised when pairs is not a torch.Tensor at all (list, tuple, numpy array, float, None).","triggerScenarios":"set_pair_postprocess_by_name('dual_sigma_shift', ...) with a subsequent call where the pairs argument is a Python list, numpy.ndarray, or scalar — e.g. a schedule produced by numpy.linspace or deserialized from JSON/config.","commonSituations":"Config-driven pipelines that deserialize schedules from JSON/YAML into lists; numpy-based schedule generation not converted to torch; passing None when the scheduler cache is empty.","solutions":["Convert to a tensor before use: pairs = torch.as_tensor(pairs, dtype=torch.float32)","Prefer scheduler-native set_timesteps so pairs are always torch.Tensor [N, 2]","Add an isinstance assertion at the boundary of your custom loop","Return early / skip the postprocess when pairs is None instead of passing it through"],"exampleFix":"# before\npost_pairs = np.linspace(1.0, 0.0, num_steps)  # ndarray\n\n# after\npost_pairs = torch.as_tensor(np.linspace(1.0, 0.0, num_steps), dtype=torch.float32)\npost_pairs = torch.stack([post_pairs, post_pairs], dim=1)","handlingStrategy":"validation","validationCode":"if not isinstance(pairs, torch.Tensor):\n    pairs = torch.as_tensor(pairs, dtype=torch.float32)","typeGuard":"def is_pairs_tensor(p) -> TypeGuard[torch.Tensor]:\n    return isinstance(p, torch.Tensor) and p.ndim == 2 and p.shape[1] == 2","tryCatchPattern":"try:\n    out = scheduler.step(...)\nexcept TypeError as e:\n    if 'pairs must be a torch.Tensor' in str(e):\n        pairs = torch.as_tensor(pairs).reshape(-1, 2)\n        out = scheduler.step(...)  # retry with normalized input\n    else:\n        raise","preventionTips":["Ban numpy arrays at your pipeline boundary; convert once at ingestion","Deserialize schedules from config with torch.as_tensor immediately"],"tags":["pytorch","type-check","scheduler","sigma-shift","validation"],"backgroundTag":"wrong-argument-type","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}