nodejs/node · error · ValueError
{name} key {key} must be list, not {value.__class__.__name__
Error message
{name} key {key} must be list, not {value.__class__.__name__} What it means
ProcessListFiltersInDict handles keys ending in '!' (exclusion) or '/' (regex). The value paired with such a key MUST be a list. If value is not a list, gyp raises ValueError (note: ValueError, not GypError) naming the key, its expected list type, and the actual class.
Source
Thrown at tools/gyp/pylib/gyp/input.py:2532
# Look through the dictionary for any lists whose keys end in "!" or "/".
# These are lists that will be treated as exclude lists and regular
# expression-based exclude/include lists. Collect the lists that are
# needed first, looking for the lists that they operate on, and assemble
# then into |lists|. This is done in a separate loop up front, because
# the _included and _excluded keys need to be added to the_dict, and that
# can't be done while iterating through it.
lists = []
del_lists = []
for key, value in the_dict.items():
if not key:
continue
operation = key[-1]
if operation not in {"!", "/"}:
continue
if not isinstance(value, list):
raise ValueError(
name + " key " + key + " must be list, not " + value.__class__.__name__
)
list_key = key[:-1]
if list_key not in the_dict:
# This happens when there's a list like "sources!" but no corresponding
# "sources" list. Since there's nothing for it to operate on, queue up
# the "sources!" list for deletion now.
del_lists.append(key)
continue
if not isinstance(the_dict[list_key], list):
value = the_dict[list_key]
raise ValueError(
name
+ " key "
+ list_key
+ " must be list, not "View on GitHub (pinned to 1b2de5e052)
Solutions
- Make the value of any '!'/''/' key a list, e.g. 'sources!': ['bad.cc'].
Example fix
// before: 'sources!': 'generated.cc' // after: 'sources!': ['generated.cc']
Defensive patterns
Strategy: type-guard
Validate before calling
for k, v in the_dict.items():
if k[-1:] in ('!', '/'):
assert isinstance(v, list), '%s must be a list' % k
Type guard
def filter_value_is_list(d, k): return isinstance(d.get(k), list)
Try / catch
try:
gyp.main(args)
except ValueError as e:
if 'must be list' in str(e): print('Make the filter value a list'); raise Prevention
- Always use list brackets for '!'/ and '/' keys.
- Lint exclusion/regex keys for list values.
- Avoid scalar shorthand for filters.
When it happens
Trigger: A dict contains a key ending in '!' or '/' (e.g. 'sources!', 'sources/') whose value is not a Python list (e.g. a string, dict, or None).
Common situations: Typing 'sources!' as a string instead of a list; copy-paste that dropped the list brackets; generator emitting a scalar for an exclusion key; confusing the exclusion syntax with a single-item shorthand.
Related errors
- {name} key {list_key} must be list, not {value.__class__.__n
- Unrecognized action {action} in {name} key {regex_key}
- {name} key {excluded_key} must not be present prior to appl
- Found wildcard in {dependency_key} of {target} referring to
- Missing 'target_name' field in target.
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/2699d1d8fdbe492f.
Report an issue: GitHub.