sgl-project/sglang · error · ValueError

kv-canary: WritePlan write_req_capacity must be positive, go

Error message

kv-canary: WritePlan write_req_capacity must be positive, got {write_req_capacity}

What it means

WritePlan.allocate requires write_req_capacity > 0 because it allocates write_offsets of size capacity+1 (CSR-style offsets) and a zero/negative capacity would produce a degenerate or negative-size tensor. It is an argument sanity check in the plan factory.

Source

Thrown at python/sglang/kernels/ops/kv_canary/write.py:57

        write_seed_slot_indices: Chain-seed slot per write req, shape [write_req_capacity], int64. Already
            SWA-translated. -1 = no prefix (chain anchors on CANARY_CHAIN_ANCHOR).
        write_num_valid_reqs: Active write-req count, shape [1], int32. launch_canary_write_kernel skips blocks
            with block_id >= write_num_valid_reqs[0].
    """

    write_offsets: torch.Tensor
    write_seed_slot_indices: torch.Tensor
    write_num_valid_reqs: torch.Tensor

    @classmethod
    def allocate(
        cls,
        *,
        write_req_capacity: int,
        device: torch.device,
    ) -> WritePlan:
        if write_req_capacity <= 0:
            raise ValueError(
                f"kv-canary: WritePlan write_req_capacity must be positive, got {write_req_capacity}"
            )
        return cls(
            write_offsets=torch.empty(
                write_req_capacity + 1, dtype=torch.int64, device=device
            ),
            write_seed_slot_indices=torch.empty(
                write_req_capacity, dtype=torch.int64, device=device
            ),
            write_num_valid_reqs=torch.empty(1, dtype=torch.int32, device=device),
        )

    def zero_for_testing_(self) -> WritePlan:
        """WARN: ONLY use it when testing plan kernel. Do not use it when testing verify or
        write kernel to avoid hiding bugs."""
        self.write_offsets.zero_()
        self.write_seed_slot_indices.zero_()
        self.write_num_valid_reqs.zero_()

View on GitHub (pinned to 0132848349)

Solutions

  1. Skip the canary write entirely when there are no requests rather than allocating a plan
  2. Ensure the capacity expression (e.g. num_reqs or max tokens) is >= 1 before calling
  3. Trace where write_req_capacity comes from and fix the off-by-one/underflow

Example fix

# before
plan = WritePlan.allocate(write_req_capacity=num_reqs, device=dev)
# after
plan = WritePlan.allocate(write_req_capacity=max(num_reqs, 1), device=dev) if num_reqs else None
Defensive patterns

Strategy: validation

Validate before calling

if write_req_capacity <= 0:
    return  # nothing to write
plan = WritePlan.allocate(write_req_capacity=write_req_capacity, device=dev)

Type guard

def is_valid_write_capacity(c: int) -> bool:
    return isinstance(c, int) and c > 0

Prevention

When it happens

Trigger: Calling WritePlan.allocate(write_req_capacity=0, device=...) or with a negative value, typically when the value is derived from a request count that is 0 (empty batch).

Common situations: Running a write pass on a batch with no requests; capacity computed as len(reqs) - something that underflowed; tests with degenerate inputs.

Related errors


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