{"record":{"id":"442627dbe80c21a0","repo":"sgl-project/sglang","slug":"num-draft-layers-must-be-positive-got-num-draft","errorCode":null,"errorMessage":"num_draft_layers must be positive, got {num_draft_layers}.","messagePattern":"num_draft_layers must be positive, got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/speculative/dflash_utils.py","lineNumber":375,"sourceCode":"\n    Args:\n        num_target_layers: Number of transformer layers in the runtime target model.\n        num_draft_layers: Number of layers in the DFlash draft model.\n\n    Returns:\n        A list of 0-based target layer indices of length `num_draft_layers`.\n\n    Notes:\n        - DFlash uses hidden states after each selected target layer (HF-style).\n        - SGLang captures \"before layer i\", so the model hook will typically add +1\n          when mapping to capture points.\n    \"\"\"\n    if num_target_layers <= 0:\n        raise ValueError(\n            f\"num_target_layers must be positive, got {num_target_layers}.\"\n        )\n    if num_draft_layers <= 0:\n        raise ValueError(f\"num_draft_layers must be positive, got {num_draft_layers}.\")\n\n    if num_draft_layers == 1:\n        return [num_target_layers // 2]\n\n    start = 1\n    end = num_target_layers - 3\n    if end < start:\n        raise ValueError(\n            \"DFlash layer selection requires num_target_layers >= 4. \"\n            f\"Got num_target_layers={num_target_layers}.\"\n        )\n\n    span = end - start\n    return [\n        int(round(start + (i * span) / (num_draft_layers - 1)))\n        for i in range(num_draft_layers)\n    ]\n","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/speculative/dflash_utils.py#L357-L393","documentation":"Raised by build_target_layer_ids when num_draft_layers <= 0. The function spreads draft layers across target layer positions, so at least one draft layer is required. A non-positive draft layer count indicates the speculative draft config is malformed.","triggerScenarios":"Calling build_target_layer_ids(num_target_layers=N, num_draft_layers=0), typically from resolve_target_layer_ids when the DFlashDraftConfig has num_draft_layers unset/0.","commonSituations":"Draft config JSON with speculative_num_draft_layers: 0; CLI flag --speculative-num-draft-tokens confused with draft layers and set to 0; a draft config parsed from a HF repo where the field is missing and defaulted to 0.","solutions":["Set the draft layer count to >= 1 in the draft config / server args (e.g. --speculative-num-draft-tokens vs --speculative-num-steps style flags — use the one controlling draft layers).","Validate parse_dflash_draft_config output before launching; require_num_layers and the draft-layer field should both be positive.","Re-check the DFLASH draft config JSON from the model repo for the correct field names."],"exampleFix":"# before\nbuild_target_layer_ids(num_target_layers=32, num_draft_layers=0)\n# after\nbuild_target_layer_ids(num_target_layers=32, num_draft_layers=1)","handlingStrategy":"validation","validationCode":"if not isinstance(num_draft_layers, int) or num_draft_layers < 1:\n    raise ValueError('num_draft_layers must be >= 1')","typeGuard":"def is_valid_draft_layers(v) -> bool:\n    return isinstance(v, int) and v >= 1","tryCatchPattern":null,"preventionTips":["Don't use 0 to 'disable' a draft field — omit it or use null.","Validate parsed DFlashDraftConfig fields immediately after parse_dflash_draft_config."],"tags":["speculative-decoding","dflash","config-validation"],"backgroundTag":"invalid-config-value","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}