nodejs/node · error · GypError
%s %s must be followed by a dictionary, not %s
Error message
%s %s must be followed by a dictionary, not %s
What it means
In a condition triple [cond_expr, true_dict, (false_dict)], the element immediately after cond_expr must be a dict — the set of keys merged into the enclosing dict when the condition holds. If that second element is a list, string, or any non-dict, EvalCondition raises this GypError naming conditions_key, the cond_expr, and the offending Python type. The false_dict (third element) is optional and only consumed if it too is a dict.
Source
Thrown at tools/gyp/pylib/gyp/input.py:1134
raise GypError(conditions_key + " must be a list")
if len(condition) < 2:
# It's possible that condition[0] won't work in which case this
# attempt will raise its own IndexError. That's probably fine.
raise GypError(
conditions_key
+ " "
+ condition[0]
+ " 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
)View on GitHub (pinned to 1b2de5e052)
Solutions
- Make the second element a dict, e.g. { 'defines': ['IS_MAC'], 'sources': [...] }.
- Move list-valued content (defines, sources) inside that dict under the appropriate key.
- If you intended a nested condition, place another 'conditions' key inside the true_dict.
Example fix
// before
'conditions': [ ['OS == "mac"', ['IS_MAC']] ],
// after
'conditions': [ ['OS == "mac"', { 'defines': ['IS_MAC'] }] ], Defensive patterns
Strategy: type-guard
Validate before calling
def validate_condition(entry, key='conditions'):
assert isinstance(entry, list) and len(entry) >= 2
assert isinstance(entry[1], dict), \
f'{key} {entry[0]!r} true branch must be a dict, got {type(entry[1]).__name__}' Type guard
def true_branch_is_dict(entry) -> bool:
return isinstance(entry, list) and len(entry) >= 2 and isinstance(entry[1], dict) Prevention
- Place keys like 'defines'/'sources' inside the true_dict, not as a bare list at index 1.
- When refactoring, double-check the second slot of every condition triple.
When it happens
Trigger: Writing "['OS==\"mac\"', ['IS_MAC']]" — a list instead of a dict as the true body; putting a bare string or a second condition expression where the true_dict belongs; nesting condition lists flatly instead of grouping them.
Common situations: Confusing the condition body with a list of defines; misreading the triple structure and supplying [expr, value, value]; refactoring that moves a list into the wrong slot.
Related errors
- %s must be a list
- %s %s must be at least length 2, not %s
- {conditions_key} {cond_expr} has {len(condition) - i} unexpe
- Variable expansion in this context permits str and int only,
- Unknown type {value.__class__.__name__} for {key}
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/348019137b8ca3af.
Report an issue: GitHub.