nodejs/node · error · GypError

{conditions_key} {cond_expr} has {len(condition) - i} unexpe

Error message

{conditions_key} {cond_expr} has {len(condition) - i} unexpected trailing items

What it means

When a condition entry has three elements [cond_expr, true_dict, false_dict] (all three present and false_dict a dict), EvalCondition advances its index by 3 and then requires that index to equal the list length. Any extra elements after the false_dict are reported as 'unexpected trailing items' with the count. This catches malformed conditions that tack on additional bare expressions or dicts beyond the standard triple.

Source

Thrown at tools/gyp/pylib/gyp/input.py:1142

            + " must be at least length 2, not "
            + str(len(condition))
        )

    i = 0
    result = None
    while i < len(condition):
        cond_expr = condition[i]
        true_dict = condition[i + 1]
        if not isinstance(true_dict, dict):
            raise GypError(
                f"{conditions_key} {cond_expr} must be followed by a dictionary, "
                f"not {type(true_dict)}"
            )
        if len(condition) > i + 2 and isinstance(condition[i + 2], dict):
            false_dict = condition[i + 2]
            i = i + 3
            if i != len(condition):
                raise GypError(
                    f"{conditions_key} {cond_expr} has "
                    f"{len(condition) - i} unexpected trailing items"
                )
        else:
            false_dict = None
            i = i + 2
        if result is None:
            result = EvalSingleCondition(
                cond_expr, true_dict, false_dict, phase, variables, build_file
            )

    return result


def EvalSingleCondition(cond_expr, true_dict, false_dict, phase, variables, build_file):
    """Returns true_dict if cond_expr evaluates to true, and false_dict
    otherwise."""
    # Do expansions on the condition itself.  Since the condition can naturally

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Express additional branches as separate entries in the outer conditions list — each entry is one [expr, true_dict, (false_dict)].
  2. Remove the trailing elements reported by the count in the message.
  3. For if/elif chains, use nested 'conditions' inside the false_dict.

Example fix

// before
'conditions': [
  ['OS == "mac"', { 'defines': ['M'] }, { 'defines': ['L'] }, 'extra']
],
// after
'conditions': [
  ['OS == "mac"', { 'defines': ['M'] }, { 'defines': ['L'] }]
],
Defensive patterns

Strategy: validation

Validate before calling

def validate_condition(entry, key='conditions'):
    if len(entry) >= 3 and isinstance(entry[2], dict):
        assert len(entry) == 3, \
            f'{key} {entry[0]!r} has unexpected trailing items beyond [expr, true, false]'

Type guard

def has_no_trailing_items(entry) -> bool:
    if isinstance(entry, list) and len(entry) >= 3 and isinstance(entry[2], dict):
        return len(entry) == 3
    return True

Prevention

When it happens

Trigger: Writing "['OS==\"mac\"', {true}, {false}, 'extra']"; chaining multiple cond_exprs in a single list instead of using multiple list entries; copy-paste that duplicated the false_dict.

Common situations: Trying to express if/elif by listing extra items in one condition rather than as separate top-level condition entries; accidental duplicate paste of a dict.

Related errors


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