{"record":{"id":"e717286d670ad0b7","repo":"sgl-project/sglang","slug":"diff-threshold-expects-a-single-float-shorthand","errorCode":null,"errorMessage":"--diff-threshold expects a single float shorthand or (regex predicate) pairs; got an odd number of arguments: {raw}","messagePattern":"--diff-threshold expects a single float shorthand or \\(regex predicate\\) pairs; got an odd number of arguments: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/debug_utils/comparator/threshold_dsl.py","lineNumber":35,"sourceCode":"\n\ndef parse_diff_threshold_rules(\n    raw: Optional[list[str]], *, default_predicate: str\n) -> list[DiffThresholdRule]:\n    if not raw:\n        return [DiffThresholdRule(\".*\", default_predicate)]\n    if len(raw) == 1:\n        try:\n            value = float(raw[0])\n        except ValueError as e:\n            raise ValueError(\n                f\"--diff-threshold with a single argument must be a float shorthand \"\n                f\"(e.g. 0.0085); got {raw[0]!r}. For per-regex predicates pass \"\n                f\"(regex predicate) pairs.\"\n            ) from e\n        return [DiffThresholdRule(\".*\", f\"rel <= {value}\")]\n    if len(raw) % 2 != 0:\n        raise ValueError(\n            f\"--diff-threshold expects a single float shorthand or (regex predicate) \"\n            f\"pairs; got an odd number of arguments: {raw}\"\n        )\n    rules = [DiffThresholdRule(raw[i], raw[i + 1]) for i in range(0, len(raw), 2)]\n    for rule in rules:\n        parse_predicate(rule.predicate)\n    return rules\n\n\ndef resolve_predicate(\n    name: str,\n    diff_threshold_rules: Optional[list[DiffThresholdRule]],\n    *,\n    default_predicate: str,\n) -> str:\n    if not diff_threshold_rules:\n        return default_predicate\n    for rule in diff_threshold_rules:","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/debug_utils/comparator/threshold_dsl.py#L17-L53","documentation":"parse_diff_threshold_rules raises this when the --diff-threshold argument list has an odd number of elements (>1). Per-regex rules are consumed as (regex predicate) pairs, so any leftover token means a regex is missing its predicate or vice versa.","triggerScenarios":"Calling parse_diff_threshold_rules(['a.*','rel <= 1','b.*']) — three tokens — or a CLI invocation where one pair member was forgotten or a space split a pair incorrectly.","commonSituations":"Forgetting the predicate half of a pair, shell quoting dropping an argument, or appending an extra flag value to the same list.","solutions":["Add the missing predicate (or remove the dangling regex) so the list has an even length","Verify shell quoting: each regex and each predicate must arrive as separate argv entries","Pre-validate with a simple len(raw) % 2 == 0 check in wrapper scripts"],"exampleFix":"# before\nparse_diff_threshold_rules(['blk0.*','rel <= 0.01','blk1.*'])\n# after\nparse_diff_threshold_rules(['blk0.*','rel <= 0.01','blk1.*','rel <= 0.01'])","handlingStrategy":"validation","validationCode":"if len(raw) > 1 and len(raw) % 2 != 0:\n    raise SystemExit(f'odd number of --diff-threshold args: {raw}')","typeGuard":null,"tryCatchPattern":"try:\n    rules = parse_diff_threshold_rules(raw)\nexcept ValueError as e:\n    print(e); sys.exit(2)","preventionTips":["Check len(args) % 2 == 0 in wrapper scripts","Quote each regex and predicate separately in shell commands"],"tags":["cli","parsing","arity","threshold"],"backgroundTag":"invalid-argument-arity","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}