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

  1. 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

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


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