{"record":{"id":"7aa2d0db0fb77c84","repo":"nodejs/node","slug":"attempt-to-merge-dict-value-of-type-v-class","errorCode":null,"errorMessage":"Attempt to merge dict value of type {v.__class__.__name__} into incompatible type {to[k].__class__.__name__} for key {k}","messagePattern":"Attempt to merge dict value of type (.+?) into incompatible type (.+?) for key (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":2289,"sourceCode":"\ndef MergeDicts(to, fro, to_file, fro_file):\n    # I wanted to name the parameter \"from\" but it's a Python keyword...\n    for k, v in fro.items():\n        # It would be nice to do \"if not k in to: to[k] = v\" but that wouldn't give\n        # copy semantics.  Something else may want to merge from the |fro| dict\n        # later, and having the same dict ref pointed to twice in the tree isn't\n        # what anyone wants considering that the dicts may subsequently be\n        # modified.\n        if k in to:\n            bad_merge = False\n            if type(v) in (str, int):\n                if type(to[k]) not in (str, int):\n                    bad_merge = True\n            elif not isinstance(v, type(to[k])):\n                bad_merge = True\n\n            if bad_merge:\n                raise TypeError(\n                    \"Attempt to merge dict value of type \"\n                    + v.__class__.__name__\n                    + \" into incompatible type \"\n                    + to[k].__class__.__name__\n                    + \" for key \"\n                    + k\n                )\n        if type(v) in (str, int):\n            # Overwrite the existing value, if any.  Cheap and easy.\n            is_path = IsPathSection(k)\n            if is_path:\n                to[k] = MakePathRelative(to_file, fro_file, v)\n            else:\n                to[k] = v\n        elif isinstance(v, dict):\n            # Recurse, guaranteeing copies will be made of objects that require it.\n            if k not in to:\n                to[k] = {}","sourceCodeStart":2271,"sourceCodeEnd":2307,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L2271-L2307","documentation":"MergeDicts checks type compatibility when a key already exists in the destination 'to'. str and int are mutually compatible (both treated as scalars); for any other pair the types must match exactly (isinstance(v, type(to[k]))). On mismatch it raises TypeError naming both types and the key.","triggerScenarios":"Merging a dict where key k already exists in 'to' with value to[k], and the incoming v has an incompatible type — e.g. to[k] is a list but v is a str, or to[k] is a dict but v is an int.","commonSituations":"An include (.gypi) overriding a scalar with a list or vice-versa; a configuration base setting a dict where the target set a string; conflicting default vs platform-specific values; bad variable expansion changing a value's type.","solutions":["Make the two values the same type for key k (both scalar str/int, or both list, or both dict).","Remove the conflicting value from one of the merging sources (include vs target vs configuration).","Use list-policy suffixes (= ? +) intentionally for list keys instead of mixing types.","Trace which MergeDicts call (settings propagation) introduces the conflicting value."],"exampleFix":"// before: target has 'cflags': '-O2' but include merges 'cflags': ['-O2']\n// after: use consistent list form in both: 'cflags': ['-O2']","handlingStrategy":"type-guard","validationCode":"def compatible(a, b):\n    if type(a) in (str, int) and type(b) in (str, int): return True\n    return isinstance(a, type(b)) and isinstance(b, type(a))\nfor k, v in fro.items():\n    if k in to and not compatible(to[k], v):\n        raise TypeError('type clash on %s' % k)\n","typeGuard":"def types_compatible(a, b):\n    if type(a) in (str,int) and type(b) in (str,int): return True\n    return isinstance(a, type(b))","tryCatchPattern":"try:\n    MergeDicts(to, fro, to_file, fro_file)\nexcept TypeError as e:\n    if 'incompatible type' in str(e): print('Align value types for the conflicting key'); raise","preventionTips":["Keep the same value type for a key across target/include/configuration.","Don't override a scalar with a list or vice-versa.","Use list-policy suffixes deliberately for list keys."],"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"}