sgl-project/sglang · error · ValueError

{name} must be a CUDA tensor

Error message

{name} must be a CUDA tensor

What it means

Both q_scale and kv_scale must be CUDA tensors; the kernel reads them from GPU memory during the q8kv8 attention computation. A CPU tensor would produce an invalid device pointer at kernel launch, so the wrapper rejects it in Python.

Source

Thrown at python/sglang/kernels/ops/attention/sparse_mla_q8kv8_prefill_sm90.py:425

        if attn_sink.shape != (h_q,) or attn_sink.dtype != torch.float32:
            raise ValueError(
                f"attn_sink must be float32 with shape ({h_q},), got "
                f"{tuple(attn_sink.shape)}/{attn_sink.dtype}"
            )
        if not attn_sink.is_cuda:
            raise ValueError("attn_sink must be a CUDA tensor")
        if attn_sink.device != device:
            raise ValueError(
                f"attn_sink must be on q's device {device}, got {attn_sink.device}"
            )
        if not attn_sink.is_contiguous():
            raise ValueError("attn_sink must be contiguous")

    for name, scale in (("q_scale", q_scale), ("kv_scale", kv_scale)):
        if not isinstance(scale, torch.Tensor):
            raise ValueError(f"{name} must be a torch.Tensor")
        if not scale.is_cuda:
            raise ValueError(f"{name} must be a CUDA tensor")
        if scale.device != device:
            raise ValueError(
                f"{name} must be on q's device {device}, got {scale.device}"
            )
        if scale.dtype != torch.float32:
            raise ValueError(f"{name} must be float32, got {scale.dtype}")
        if scale.numel() != 1:
            raise ValueError(
                f"{name} must be a scalar tensor, got shape {tuple(scale.shape)}"
            )
        if not scale.is_contiguous():
            raise ValueError(f"{name} must be contiguous")

    if out is None:
        out = torch.empty(s_q, h_q, d_v, dtype=torch.bfloat16, device=device)
    else:
        _check_out_buffer(out, "out", (s_q, h_q, d_v), torch.bfloat16, device)

View on GitHub (pinned to 0132848349)

Solutions

  1. Create the scale with device=q.device
  2. Or move existing CPU scales: q_scale = q_scale.to(q.device)

Example fix

// before
q_scale = torch.tensor(1.0, dtype=torch.float32)  # CPU
// after
q_scale = torch.tensor(1.0, dtype=torch.float32, device=q.device)
Defensive patterns

Strategy: validation

Validate before calling

assert q_scale.is_cuda and kv_scale.is_cuda

Prevention

When it happens

Trigger: Passing torch.tensor(1.0) created without a device argument (defaults to CPU) as q_scale or kv_scale.

Common situations: Creating scale tensors at config-parse time on CPU and forgetting to move them when the model weights are later placed on GPU.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/3263ecea5bd77d59. Report an issue: GitHub.