{"record":{"id":"42f2cce0ee87872a","repo":"sgl-project/sglang","slug":"kv-canary-verifyplan-verify-capacity-must-be-posi","errorCode":null,"errorMessage":"kv-canary: VerifyPlan verify_capacity must be positive, got {verify_capacity}","messagePattern":"kv-canary: VerifyPlan verify_capacity must be positive, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/kv_canary/verify.py","lineNumber":203,"sourceCode":"            \"predecessor == previous array entry\" assumption.\n        verify_num_valid: Active entry count, shape [1], int32. Clamped by the plan kernel to\n            min(total_requested, verify_capacity) so the verify kernel grid never reads past the buffer.\n        enable: Run-this-step flag, shape [1], int32. 1 = verify kernel runs as usual; 0 = the plan kernel\n            detected overflow (requested > verify_capacity) and the entire verify launch is skipped this step.\n            Allocated as 1 by default; the plan kernel rewrites it every step.\n    \"\"\"\n\n    verify_slot_indices: torch.Tensor\n    verify_expected_tokens: torch.Tensor\n    verify_expected_positions: torch.Tensor\n    verify_prev_slot_indices: torch.Tensor\n    verify_num_valid: torch.Tensor\n    enable: torch.Tensor\n\n    @classmethod\n    def allocate(cls, *, verify_capacity: int, device: torch.device) -> VerifyPlan:\n        if verify_capacity <= 0:\n            raise ValueError(\n                f\"kv-canary: VerifyPlan verify_capacity must be positive, got {verify_capacity}\"\n            )\n        return cls(\n            verify_slot_indices=torch.empty(\n                verify_capacity, dtype=torch.int64, device=device\n            ),\n            verify_expected_tokens=torch.empty(\n                verify_capacity, dtype=torch.int64, device=device\n            ),\n            verify_expected_positions=torch.empty(\n                verify_capacity, dtype=torch.int64, device=device\n            ),\n            verify_prev_slot_indices=torch.empty(\n                verify_capacity, dtype=torch.int64, device=device\n            ),\n            verify_num_valid=torch.empty(1, dtype=torch.int32, device=device),\n            # enable defaults to 1 (\"run verify\") so test helpers that build a VerifyPlan\n            # directly (no plan kernel) don't have to remember to set it. Plan kernel always","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/kv_canary/verify.py#L185-L221","documentation":"VerifyPlan.allocate validates that verify_capacity is a positive integer before allocating the verify_slot_indices tensor. A zero or negative capacity is meaningless (there would be no slots to verify) so the factory rejects it immediately. This is a caller-side programming/argument error, not a runtime device failure.","triggerScenarios":"Calling VerifyPlan.allocate(verify_capacity=0, device=...) or with a negative capacity, e.g. when capacity is derived from a batch size, seq len, or request count that computed to 0 (empty batch, integer underflow, or a len() of an empty list).","commonSituations":"Passing num_verify_tokens computed as max(0, x - y) that clipped to 0 on an empty batch; unit tests constructing plans with degenerate capacities; capacity read from config defaulting to 0 before being set.","solutions":["Check the expression producing verify_capacity and make sure it is >= 1 before calling allocate; skip the verify launch entirely when there is nothing to verify","If capacity can legitimately be 0, guard the call site: if verify_capacity > 0: plan = VerifyPlan.allocate(...)","Add an assert/clamp (e.g. max(verify_capacity, 1)) only if the downstream kernel can tolerate dummy slots — otherwise treat 0 as a no-op"],"exampleFix":"// before\nplan = VerifyPlan.allocate(verify_capacity=num_verify_tokens, device=dev)\n// after\nif num_verify_tokens > 0:\n    plan = VerifyPlan.allocate(verify_capacity=num_verify_tokens, device=dev)\nelse:\n    plan = None  # nothing to verify","handlingStrategy":"validation","validationCode":"if verify_capacity <= 0:\n    raise ValueError(f\"verify_capacity must be positive, got {verify_capacity}\")\nplan = VerifyPlan.allocate(verify_capacity=verify_capacity, device=dev)","typeGuard":"def is_valid_verify_capacity(c: int) -> bool:\n    return isinstance(c, int) and c > 0","tryCatchPattern":null,"preventionTips":["Derive verify_capacity from an explicit batch/request count and skip the call when it is 0","Add an assert on capacity in test fixtures"],"tags":["kv-canary","argument-validation","capacity"],"backgroundTag":"invalid-argument-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}