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

  1. Wrap variable references in the expansion form expected for the phase, e.g. ['<(OS) == "mac"', {...}] or use automatics like '_type' which are pre-loaded.
  2. Check for typos in the identifier named in the NameError.
  3. Do not call stripped builtins (e.g. len, print) inside conditions — compute values via <() expansion instead.
  4. 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

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


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/3b9201ac14d93519. Report an issue: GitHub.