{"record":{"id":"f930f74ed68f16a2","repo":"sgl-project/sglang","slug":"in-place-vision-rope-requires-complex64-frequencie","errorCode":null,"errorMessage":"In-place vision RoPE requires complex64 frequencies, got {freqs_cis.dtype}/{freqs_cis.device}","messagePattern":"In-place vision RoPE requires complex64 frequencies, got (.+?)/(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/vision_rope.py","lineNumber":165,"sourceCode":"        k_flat.stride(0),\n        k_flat.stride(1),\n        k_flat.stride(2),\n        freqs.stride(0),\n        freqs.stride(1),\n        freqs.stride(2),\n        BLOCK=block,\n        num_warps=4,\n    )\n    return q_out.view(original_shape), k_out.view(original_shape)\n\n\ndef prepare_fused_qk_complex_rope_inplace(\n    freqs_cis: torch.Tensor,\n) -> PreparedInplaceComplexRoPE:\n    \"\"\"Prepare the cache and positions used by the contiguous in-place kernel.\"\"\"\n\n    if freqs_cis.dtype != torch.complex64:\n        raise ValueError(\n            \"In-place vision RoPE requires complex64 frequencies, got \"\n            f\"{freqs_cis.dtype}/{freqs_cis.device}\"\n        )\n    return (\n        torch.cat((freqs_cis.real, freqs_cis.imag), dim=-1),\n        torch.arange(\n            freqs_cis.size(0),\n            dtype=torch.long,\n            device=freqs_cis.device,\n        ),\n    )\n\n\ndef apply_fused_qk_complex_rope_inplace(\n    q: torch.Tensor,\n    k: torch.Tensor,\n    prepared_rope: PreparedInplaceComplexRoPE,\n) -> Tuple[torch.Tensor, torch.Tensor]:","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/vision_rope.py#L147-L183","documentation":"prepare_fused_qk_complex_rope_inplace prepares a cache by concatenating freqs_cis.real and freqs_cis.imag along the last dim; that split only exists for complex tensors, so freqs_cis must be torch.complex64. Any other dtype (float32 stored as interleaved real/imag, complex128) is rejected before the split.","triggerScenarios":"Passing a float32 tensor of shape (..., 2*half) that packs real and imag channels (a common memory layout after slicing a projection) instead of an actual complex64 tensor.","commonSituations":"Vision towers whose RoPE tables are materialized as real tensors for convolution-friendly layouts, then fed to the in-place fused path which expects torch.view_as_complex-style complex64 input.","solutions":["Convert: freqs = torch.view_as_complex(freqs_float.reshape(*freqs_float.shape[:-1], -1, 2).contiguous()) when the data is interleaved real/imag","Or build the table with torch.polar(abs, angle) which produces complex64 directly"],"exampleFix":"// before\nprepared = prepare_fused_qk_complex_rope_inplace(freqs_float32)  # (T, D/2, 2)\n// after\nfreqs_cis = torch.view_as_complex(freqs_float32.contiguous())\nprepared = prepare_fused_qk_complex_rope_inplace(freqs_cis)","handlingStrategy":"validation","validationCode":"assert freqs_cis.dtype == torch.complex64, 'freqs must be complex64'","typeGuard":"def is_c64(t: torch.Tensor) -> bool:\n    return t.dtype == torch.complex64","tryCatchPattern":null,"preventionTips":["Build RoPE tables with torch.polar or view_as_complex so dtype is complex64 by construction","Avoid hand-packed real/imag float layouts when the consumer expects complex tensors"],"tags":["vision-rope","dtype","complex-tensor"],"backgroundTag":"wrong-tensor-dtype","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}