{"record":{"id":"3b9201ac14d93519","repo":"nodejs/node","slug":"while-evaluating-condition-cond-expr-expanded","errorCode":null,"errorMessage":"while evaluating condition '{cond_expr_expanded}' in {build_file}","messagePattern":"while evaluating condition '(.+?)' in (.+?)","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":1197,"sourceCode":"        if eval(ast_code, env, variables):\n            return true_dict\n        return false_dict\n    except SyntaxError as e:\n        syntax_error = SyntaxError(\n            \"%s while evaluating condition '%s' in %s \"\n            \"at character %d.\" % (str(e.args[0]), e.text, build_file, e.offset),\n            e.filename,\n            e.lineno,\n            e.offset,\n            e.text,\n        )\n        raise syntax_error\n    except NameError as e:\n        gyp.common.ExceptionAppend(\n            e,\n            f\"while evaluating condition '{cond_expr_expanded}' in {build_file}\",\n        )\n        raise GypError(e)\n\n\ndef ProcessConditionsInDict(the_dict, phase, variables, build_file):\n    # Process a 'conditions' or 'target_conditions' section in the_dict,\n    # depending on phase.\n    # early -> conditions\n    # late -> target_conditions\n    # latelate -> no conditions\n    #\n    # Each item in a conditions list consists of cond_expr, a string expression\n    # evaluated as the condition, and true_dict, a dict that will be merged into\n    # the_dict if cond_expr evaluates to true.  Optionally, a third item,\n    # false_dict, may be present.  false_dict is merged into the_dict if\n    # cond_expr evaluates to false.\n    #\n    # Any dict merged into the_dict will be recursively processed for nested\n    # conditionals and other expansions, also according to phase, immediately\n    # prior to being merged.","sourceCodeStart":1179,"sourceCodeEnd":1215,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L1179-L1215","documentation":"EvalSingleCondition compiles and eval's the expanded condition string with a restricted environment ({__builtins__:{}, v:Version}). If eval raises a NameError — typically because the expression references an identifier that is neither a variable nor the 'v' builtin — GYP appends this context message ('while evaluating condition ... in <build_file>') and re-raises as GypError. The most common cause is using an un-prefixed variable name: inside conditions you must write '<(var)' or use the automatic '_var' form, not bare 'var'.","triggerScenarios":"Writing \"['OS == \\\"mac\\\"', {...}]\" when OS is not in the eval namespace (it must be '<(OS)' or you rely on automatics like 'OS' which are only present when set); referencing 'foo' instead of '<(foo)'; typos in automatic variable names; using Python builtins that were stripped by __builtins__:{}.","commonSituations":"Forgetting that condition expressions are evaluated with a sandboxed env and almost no builtins; mixing up the '<(var)' expansion form with bare identifier references; referencing a target-scope variable that is not yet in scope during the early phase.","solutions":["Wrap variable references in the expansion form expected for the phase, e.g. ['<(OS) == \"mac\"', {...}] or use automatics like '_type' which are pre-loaded.","Check for typos in the identifier named in the NameError.","Do not call stripped builtins (e.g. len, print) inside conditions — compute values via <() expansion instead.","Confirm the variable is in scope for the current phase (early vs late vs latelate)."],"exampleFix":"// before — bare 'foo' is not defined in the eval sandbox\n'conditions': [ ['foo == \"1\"', { 'defines': ['FOO'] }] ],\n// after\n'conditions': [ ['<(foo) == \"1\"', { 'defines': ['FOO'] }] ],","handlingStrategy":"validation","validationCode":"# Sanity-test that every identifier in a condition expression is in scope or the v builtin.\nimport ast\nfor name in ast.walk(ast.parse(cond_expr, mode='eval')):\n    if isinstance(name, ast.Name) and name.id not in variables and name.id != 'v':\n        raise SystemExit(f'Condition references undefined name {name.id!r}; use <({name.id}) expansion')","typeGuard":"def condition_names_are_in_scope(cond_expr: str, variables: dict) -> bool:\n    import ast\n    tree = ast.parse(cond_expr, mode='eval')\n    return all(isinstance(n, ast.Name) and (n.id in variables or n.id == 'v')\n               or not isinstance(n, ast.Name) for n in ast.walk(tree))","tryCatchPattern":"try:\n    gyp.process_build_file(...)\nexcept gyp.input.GypError as e:\n    if 'while evaluating condition' in str(e):\n        extract_undefined_name(e)","preventionTips":["Wrap variable references in conditions as <(var)/>(var)/^(var) per phase.","Use automatics like '_type'/'_toolset' rather than guessing bare names.","Avoid calling stripped builtins (len, print) inside condition expressions."],"tags":["gyp","conditions","name-error","eval","build-config"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}