{"record":{"id":"cd68a3a27c1661fa","repo":"nodejs/node","slug":"attempt-to-merge-list-item-of-unsupported-type-it","errorCode":null,"errorMessage":"Attempt to merge list item of unsupported type {item.__class__.__name__}","messagePattern":"Attempt to merge list item of unsupported type (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":2244,"sourceCode":"                # only appear once in a list, to be enforced by the list merge append\n                # or prepend.\n                singleton = True\n        elif isinstance(item, dict):\n            # Make a copy of the dictionary, continuing to look for paths to fix.\n            # The other intelligent aspects of merge processing won't apply because\n            # item is being merged into an empty dict.\n            to_item = {}\n            MergeDicts(to_item, item, to_file, fro_file)\n        elif isinstance(item, list):\n            # Recurse, making a copy of the list.  If the list contains any\n            # descendant dicts, path fixing will occur.  Note that here, custom\n            # values for is_paths and append are dropped; those are only to be\n            # applied to |to| and |fro|, not sublists of |fro|.  append shouldn't\n            # matter anyway because the new |to_item| list is empty.\n            to_item = []\n            MergeLists(to_item, item, to_file, fro_file)\n        else:\n            raise TypeError(\n                \"Attempt to merge list item of unsupported type \"\n                + item.__class__.__name__\n            )\n\n        if append:\n            # If appending a singleton that's already in the list, don't append.\n            # This ensures that the earliest occurrence of the item will stay put.\n            if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to):\n                to.append(to_item)\n                if is_hashable(to_item):\n                    hashable_to_set.add(to_item)\n        else:\n            # If prepending a singleton that's already in the list, remove the\n            # existing instance and proceed with the prepend.  This ensures that the\n            # item appears at the earliest possible position in the list.\n            while singleton and to_item in to:\n                to.remove(to_item)\n","sourceCodeStart":2226,"sourceCodeEnd":2262,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L2226-L2262","documentation":"MergeLists accepts only three item shapes: str/int primitives (handled first), dict (recursed via MergeDicts), and list (recursed via MergeLists). The final else branch raises TypeError for anything else. Note type(item) in (str,int) is an EXACT type test, so bool (type bool, subclass of int) is NOT matched and will also fall through to this error, as will None, float, tuple, set, and custom objects.","triggerScenarios":"During a list merge (MergeLists), an element of the 'fro' list is a type other than str/int/dict/list — e.g. None (often from an empty variable expansion), a float, a tuple, a set, a bool, or a user-defined object.","commonSituations":"A variable expansion that yields None inserted into a sources/defines list; a generator injecting non-primitive objects; JSON/eval producing floats or tuples; booleans used as flags inside list-valued keys.","solutions":["Ensure every element in list-valued .gyp keys is a string, int, dict, or list.","Replace None-producing variable expansions with a default string or omit them.","Convert floats/booleans to strings explicitly before they reach gyp.","Audit custom generators that populate list fields."],"exampleFix":"// before: 'defines': ['FOO', None, 1.5]\n// after: 'defines': ['FOO', 'BAR', '15']","handlingStrategy":"type-guard","validationCode":"def clean_list(lst):\n    out = []\n    for x in lst:\n        if type(x) in (str, int) and type(x) is not bool:\n            out.append(x)\n        elif isinstance(x, (dict, list)):\n            out.append(x)\n        else:\n            raise TypeError('unsupported list item: %r' % x)\n    return out\n","typeGuard":"def is_mergeable_item(x): return (type(x) in (str, int) and type(x) is not bool) or isinstance(x, (dict, list))","tryCatchPattern":"try:\n    MergeLists(to, fro, to_file, fro_file)\nexcept TypeError as e:\n    if 'unsupported type' in str(e): print('Sanitize list values to str/int/dict/list'); raise","preventionTips":["Keep list values as str/int/dict/list only; avoid None, bool, float, tuple, set.","Default empty variable expansions to '' not None.","Lint generated .gyp data for item types."],"tags":["gyp","merge","type-error","validation","build-config"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}