nodejs/node · error · GypError
while evaluating condition '{cond_expr_expanded}' in {build_
Error message
while evaluating condition '{cond_expr_expanded}' in {build_file} What it means
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'.
Source
Thrown at tools/gyp/pylib/gyp/input.py:1197
if eval(ast_code, env, variables):
return true_dict
return false_dict
except SyntaxError as e:
syntax_error = SyntaxError(
"%s while evaluating condition '%s' in %s "
"at character %d." % (str(e.args[0]), e.text, build_file, e.offset),
e.filename,
e.lineno,
e.offset,
e.text,
)
raise syntax_error
except NameError as e:
gyp.common.ExceptionAppend(
e,
f"while evaluating condition '{cond_expr_expanded}' in {build_file}",
)
raise GypError(e)
def ProcessConditionsInDict(the_dict, phase, variables, build_file):
# Process a 'conditions' or 'target_conditions' section in the_dict,
# depending on phase.
# early -> conditions
# late -> target_conditions
# latelate -> no conditions
#
# Each item in a conditions list consists of cond_expr, a string expression
# evaluated as the condition, and true_dict, a dict that will be merged into
# the_dict if cond_expr evaluates to true. Optionally, a third item,
# false_dict, may be present. false_dict is merged into the_dict if
# cond_expr evaluates to false.
#
# Any dict merged into the_dict will be recursively processed for nested
# conditionals and other expansions, also according to phase, immediately
# prior to being merged.View on GitHub (pinned to 1b2de5e052)
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).
Example fix
// before — bare 'foo' is not defined in the eval sandbox
'conditions': [ ['foo == "1"', { 'defines': ['FOO'] }] ],
// after
'conditions': [ ['<(foo) == "1"', { 'defines': ['FOO'] }] ], Defensive patterns
Strategy: validation
Validate before calling
# Sanity-test that every identifier in a condition expression is in scope or the v builtin.
import ast
for name in ast.walk(ast.parse(cond_expr, mode='eval')):
if isinstance(name, ast.Name) and name.id not in variables and name.id != 'v':
raise SystemExit(f'Condition references undefined name {name.id!r}; use <({name.id}) expansion') Type guard
def condition_names_are_in_scope(cond_expr: str, variables: dict) -> bool:
import ast
tree = ast.parse(cond_expr, mode='eval')
return all(isinstance(n, ast.Name) and (n.id in variables or n.id == 'v')
or not isinstance(n, ast.Name) for n in ast.walk(tree)) Try / catch
try:
gyp.process_build_file(...)
except gyp.input.GypError as e:
if 'while evaluating condition' in str(e):
extract_undefined_name(e) Prevention
- 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.
When it happens
Trigger: 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__:{}.
Common situations: 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.
Related errors
- %s must be a list
- %s %s must be at least length 2, not %s
- %s %s must be followed by a dictionary, not %s
- {conditions_key} {cond_expr} has {len(condition) - i} unexpe
- Variable expansion in this context permits str and int only,
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/3b9201ac14d93519.
Report an issue: GitHub.