{"record":{"id":"402b075a54fc5172","repo":"sgl-project/sglang","slug":"num-target-layers-must-be-positive-got-num-targe","errorCode":null,"errorMessage":"num_target_layers must be positive, got {num_target_layers}.","messagePattern":"num_target_layers must be positive, got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/speculative/dflash_utils.py","lineNumber":371,"sourceCode":"\n\ndef build_target_layer_ids(num_target_layers: int, num_draft_layers: int) -> List[int]:\n    \"\"\"Select target layer indices used to build DFlash context features.\n\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 [","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/speculative/dflash_utils.py#L353-L389","documentation":"Raised by build_target_layer_ids when num_target_layers <= 0. DFlash speculatively decodes by capturing target-model hidden states at selected intermediate layers, which requires knowing a positive number of target layers. This is a config plumbing error, not a runtime data error.","triggerScenarios":"Calling build_target_layer_ids(num_target_layers=0 or negative, num_draft_layers=N), usually via resolve_target_layer_ids when the draft config lacks a valid hidden-layer count for the target model.","commonSituations":"Target model config has no num_hidden_layers (unusual architecture or partial config); a draft config JSON where the target layer count was typo'd as 0; text_config nesting not resolving so the layer count comes back as 0/None coerced.","solutions":["Pass the target model's actual num_hidden_layers (e.g. from config.text_config.num_hidden_layers).","If loading from a DFLASH draft config override, fix the num_hidden_layers/layer-count entry to a positive integer.","Inspect the HF config actually loaded (print config) to confirm where num_hidden_layers lives."],"exampleFix":"# before\nbuild_target_layer_ids(num_target_layers=0, num_draft_layers=2)\n# after\nbuild_target_layer_ids(num_target_layers=config.text_config.num_hidden_layers, num_draft_layers=2)","handlingStrategy":"validation","validationCode":"if not isinstance(num_target_layers, int) or num_target_layers <= 0:\n    raise ValueError('num_target_layers must be a positive int')","typeGuard":"def has_valid_layer_count(cfg) -> bool:\n    n = getattr(getattr(cfg, 'text_config', cfg), 'num_hidden_layers', None)\n    return isinstance(n, int) and n > 0","tryCatchPattern":null,"preventionTips":["Run a config sanity check at startup: target and draft layer counts must both be positive ints.","Log resolved layer counts before layer-id resolution."],"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"}