{"record":{"id":"8a1ad6c8ed9b576c","repo":"sgl-project/sglang","slug":"verifycommit-committed-tokens-must-be-non-empty-r","errorCode":null,"errorMessage":"VerifyCommit committed_tokens must be non-empty: request_id={self.request_id} pre_verify_committed_len={self.pre_verify_committed_len}","messagePattern":"VerifyCommit committed_tokens must be non-empty: request_id=(.+?) pre_verify_committed_len=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/speculative/decoupled_spec_io.py","lineNumber":95,"sourceCode":"    and sometimes needs to truncate tokens / reprefill.\n    \"\"\"\n\n    request_id: str\n    src_verifier_rank: int\n    dst_drafter_rank: int\n    pre_verify_committed_len: int\n    committed_tokens: list[int]\n\n    @property\n    def draft_key(self) -> DraftReqKey:\n        return DraftReqKey(\n            src_verifier_rank=int(self.src_verifier_rank),\n            request_id=self.request_id,\n        )\n\n    def validate_committed_tokens(self) -> None:\n        if not self.committed_tokens:\n            raise ValueError(\n                \"VerifyCommit committed_tokens must be non-empty: \"\n                f\"request_id={self.request_id} \"\n                f\"pre_verify_committed_len={self.pre_verify_committed_len}\"\n            )\n        if int(self.pre_verify_committed_len) < 0:\n            raise ValueError(\n                \"VerifyCommit pre_verify_committed_len must be non-negative: \"\n                f\"request_id={self.request_id} \"\n                f\"pre_verify_committed_len={self.pre_verify_committed_len}\"\n            )\n\n\n@dataclass\nclass DraftClose:\n    request_id: str\n    src_verifier_rank: int\n    dst_drafter_rank: int\n    reason: str","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/speculative/decoupled_spec_io.py#L77-L113","documentation":"VerifyCommit.validate_committed_tokens requires that at least one token was accepted/committed by verification before appending the message to the decoupled draft scheduler stream. An empty committed_tokens list means nothing was verified, which the protocol treats as invalid state and rejects with the request_id and pre-verify committed length for debugging.","triggerScenarios":"Calling append_message (or validating) a VerifyCommit whose committed_tokens is empty — e.g. the verifier rejected every draft token and produced no accepted continuation (covered by test_empty_tokens_raises).","commonSituations":"Draft model consistently rejected (poor draft quality, temperature 0 mismatch), a bug zeroing the accepted-token list, or mishandling the 'all spec tokens rejected' case as a commit instead of an abort/reject message.","solutions":["Check committed_tokens before committing; if empty, send the appropriate reject/abort control message instead of VerifyCommit","Fix upstream logic that drops accepted tokens (off-by-one in accept_length handling)","If drafts are always fully rejected, debug draft-model compatibility/weights rather than the commit path"],"exampleFix":"# before\nmsg = VerifyCommit(key, committed_tokens=[], pre_verify_committed_len=n)\nstream.append_message(msg)\n# after\nif accepted:\n    stream.append_message(VerifyCommit(key, committed_tokens=accepted, pre_verify_committed_len=n))\nelse:\n    stream.append_message(DraftAbort(key))  # or equivalent rejection path","handlingStrategy":"validation","validationCode":"if not commit.committed_tokens:\n    # nothing accepted: use the abort/reject path instead\n    send_abort(commit.request_id)\nelse:\n    stream.append_message(commit)","typeGuard":"def is_valid_commit(commit) -> bool:\n    return bool(commit.committed_tokens) and int(commit.pre_verify_committed_len) >= 0","tryCatchPattern":"try:\n    stream.append_message(msg)\nexcept ValueError as e:\n    if \"committed_tokens must be non-empty\" in str(e):\n        handle_full_rejection(msg.request_id)\n    else:\n        raise","preventionTips":["Never emit VerifyCommit for fully-rejected drafts; use the rejection message type","Unit-test the zero-accepted-tokens edge case in verifier loops"],"tags":["sglang","speculative-decoding","decoupled","protocol-validation","empty-collection"],"backgroundTag":"empty-required-field","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}