{"record":{"id":"474cf2b6c6b86a92","repo":"sgl-project/sglang","slug":"invalid-predicate-expr-r-e-allowed-names-are","errorCode":null,"errorMessage":"invalid predicate {expr!r}: {e}; allowed names are {ALLOWED_NAMES}.","messagePattern":"invalid predicate (.+?): (.+?); allowed names are (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/debug_utils/comparator/threshold_dsl.py","lineNumber":71,"sourceCode":"    for rule in diff_threshold_rules:\n        if re.fullmatch(rule.pattern, name):\n            return rule.predicate\n    raise ValueError(\n        f\"tensor {name!r} matched no --diff-threshold pattern \"\n        f\"({[rule.pattern for rule in diff_threshold_rules]}); add a catch-all '.*' rule or a matching pattern.\"\n    )\n\n\n@lru_cache(maxsize=None)\ndef parse_predicate(expr: str) -> CodeType:\n    try:\n        code = compile(expr, \"<predicate>\", \"eval\")\n    except SyntaxError as e:\n        raise ValueError(f\"invalid predicate {expr!r}: {e}\") from e\n    try:\n        eval(code, _EVAL_GLOBALS, dict(_DUMMY_ENV))\n    except Exception as e:\n        raise ValueError(\n            f\"invalid predicate {expr!r}: {e}; allowed names are {ALLOWED_NAMES}.\"\n        ) from e\n    return code\n\n\ndef evaluate_predicate(\n    code: CodeType, *, rel: float, max_abs: float, mean_abs: float\n) -> bool:\n    return bool(\n        eval(\n            code, _EVAL_GLOBALS, {\"rel\": rel, \"max_abs\": max_abs, \"mean_abs\": mean_abs}\n        )\n    )\n","sourceCodeStart":53,"sourceCodeEnd":85,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/debug_utils/comparator/threshold_dsl.py#L53-L85","documentation":"parse_predicate raises this when the predicate compiles but evaluating it against a dummy environment raises — typically because it references a name not in ALLOWED_NAMES (the DSL's whitelist such as rel/abs/max_abs). The message lists allowed names so the developer knows exactly what is in scope.","triggerScenarios":"Calling parse_predicate('tolerance <= 0.1') where 'tolerance' is not in ALLOWED_NAMES; reached from compute_diff, parse_diff_threshold_rules, or _ev.","commonSituations":"User guesses a variable name ('diff', 'value', 'epsilon') that the whitelist doesn't provide, or uses a field only present in another version of the DSL.","solutions":["Use only the names listed in the error's 'allowed names are [...]' message, e.g. rel, abs, max_abs","Re-check spelling/case of the metric name","If a genuinely needed metric is missing, extend _EVAL_GLOBALS/ALLOWED_NAMES in threshold_dsl.py"],"exampleFix":"# before\nparse_predicate('diff <= 0.1')\n# after\nparse_predicate('rel <= 0.1')  # 'rel' is in ALLOWED_NAMES","handlingStrategy":"validation","validationCode":"from sglang.srt.debug_utils.comparator.threshold_dsl import ALLOWED_NAMES, parse_predicate\n\ndef predicate_is_valid(expr):\n    try:\n        parse_predicate(expr)\n        return True\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    parse_predicate(expr)\nexcept ValueError as e:\n    print(e); sys.exit(2)  # message lists allowed names","preventionTips":["Refer only to names in ALLOWED_NAMES (rel, abs, max_abs, ...)\nPrint ALLOWED_NAMES once to see the DSL vocabulary","Parse all predicates eagerly via parse_diff_threshold_rules to fail before the long compare"],"tags":["predicate","dsl","name-error","whitelist"],"backgroundTag":"undefined-name-in-dsl","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}