{"record":{"id":"5ea33a0baca65dfa","repo":"sgl-project/sglang","slug":"invalid-decoupled-draft-scheduler-rid-rid","errorCode":null,"errorMessage":"Invalid decoupled draft scheduler rid: {rid}","messagePattern":"Invalid decoupled draft scheduler rid: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/speculative/decoupled_spec_io.py","lineNumber":40,"sourceCode":"    src_verifier_rank: int\n    request_id: str\n\n\ndef build_draft_scheduler_rid(draft_key: DraftReqKey) -> str:\n    return f\"draft:{int(draft_key.src_verifier_rank)}:{draft_key.request_id}\"\n\n\ndef parse_draft_scheduler_rid(rid: str) -> DraftReqKey:\n    if rid.startswith(\"draft:\"):\n        encoded = rid[len(\"draft:\") :]\n        rank_text, sep, request_id = encoded.partition(\":\")\n        if sep and request_id:\n            return DraftReqKey(\n                src_verifier_rank=int(rank_text),\n                request_id=request_id,\n            )\n\n    raise ValueError(f\"Invalid decoupled draft scheduler rid: {rid}\")\n\n\n@dataclass\nclass DraftSync:\n    \"\"\"Open or re-open a drafter request from a verifier-owned prefix.\n\n    The verifier is the source of truth for committed tokens. DraftSync gives\n    the drafter the prompt and already committed output prefix that it must\n    align to before it can emit draft tail tokens.\n    \"\"\"\n\n    request_id: str\n    src_verifier_rank: int\n    dst_drafter_rank: int\n    prompt_token_ids: list[int] = field(default_factory=list)\n    committed_outputs: list[int] = field(default_factory=list)\n\n    @property","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/speculative/decoupled_spec_io.py#L22-L58","documentation":"Decoupled draft/verifier request ids are encoded as '<rank>:<request_id>' (parsed by parse_draft_scheduler_rid). If the string has no separator, an empty request_id, or a rank part that is not an integer, parsing falls through and raises this ValueError.","triggerScenarios":"Passing a raw request id without the 'rank:' prefix, an id like '0:' with empty request text, or ':req'/'abc:req' where int(rank_text) fails; exercised by test_parse_invalid_rid_raises and the colon round-trip tests.","commonSituations":"Hand-building rids instead of using DraftReqKey.format/encode; rank serialized as a non-numeric value; request_id that itself contains colons parsed from the wrong (leftmost vs rightmost) split.","solutions":["Construct the rid with the provided encoder (DraftReqKey -> its to_rid/format method) instead of string concatenation","Ensure the format is f\"{rank}:{request_id}\" with an int rank and non-empty request_id","If request_id may contain ':', split on the first colon only (partition)"],"exampleFix":"# before\nrid = request_id  # missing rank prefix\nkey = parse_draft_scheduler_rid(rid)\n# after\nrid = f\"{key.src_verifier_rank}:{key.request_id}\"\nkey = parse_draft_scheduler_rid(rid)","handlingStrategy":"type-guard","validationCode":"import re\nRID_RE = re.compile(r\"^(\\d+):(.+)$\")\nassert RID_RE.match(rid), f\"malformed rid: {rid!r}\"","typeGuard":"def is_valid_draft_rid(rid: str) -> bool:\n    rank, sep, req = rid.partition(\":\")\n    return bool(sep and req and rank.isdigit())","tryCatchPattern":"try:\n    key = parse_draft_scheduler_rid(rid)\nexcept ValueError:\n    log.warning(\"dropping malformed rid %r\", rid); return None","preventionTips":["Only build rids via the DraftReqKey encoder, never string concatenation","Split on the first colon so request ids containing ':' survive round-trips"],"tags":["sglang","speculative-decoding","decoupled","rid-parsing","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}