nodejs/node · error · GypError
Incompatible list policies {k} and {list_incompatible}
Error message
Incompatible list policies {k} and {list_incompatible} What it means
GYP list keys support merge-policy suffixes: base (append), 'base=' (replace), 'base?' (only-if-absent), 'base+' (prepend). Certain combinations are meaningless (replace+append, replace+prepend, etc.). When a suffixed key and an incompatible sibling are both present in the same 'fro' dict, gyp raises GypError listing both policies.
Source
Thrown at tools/gyp/pylib/gyp/input.py:2344
lists_incompatible = [list_base, list_base + "?"]
to[list_base] = []
elif ext == "+":
list_base = k[:-1]
lists_incompatible = [list_base + "=", list_base + "?"]
append = False
elif ext == "?":
list_base = k[:-1]
lists_incompatible = [list_base, list_base + "=", list_base + "+"]
else:
list_base = k
lists_incompatible = [list_base + "=", list_base + "?"]
# Some combinations of merge policies appearing together are meaningless.
# It's stupid to replace and append simultaneously, for example. Append
# and prepend are the only policies that can coexist.
for list_incompatible in lists_incompatible:
if list_incompatible in fro:
raise GypError(
"Incompatible list policies " + k + " and " + list_incompatible
)
if list_base in to:
if ext == "?":
# If the key ends in "?", the list will only be merged if it doesn't
# already exist.
continue
elif not isinstance(to[list_base], list):
# This may not have been checked above if merging in a list with an
# extension character.
raise TypeError(
"Attempt to merge dict value of type "
+ v.__class__.__name__
+ " into incompatible type "
+ to[list_base].__class__.__name__
+ " for key "
+ list_baseView on GitHub (pinned to 1b2de5e052)
Solutions
- Keep at most one merge policy per list base within a single dict (append and prepend are the only pair that may coexist).
- Remove the redundant/contradictory suffixed key.
- If you need replace semantics, use only 'key=' and drop the bare 'key'.
Example fix
// before: { 'sources': [...], 'sources=': [...] }
// after: { 'sources=': [...] } // replace only Defensive patterns
Strategy: validation
Validate before calling
import re
base_keys = {}
for k in the_dict:
m = re.match(r'^(.*?)([=?+/!]?)$', k)
base_keys.setdefault(m.group(1), set()).add(k)
for base, keys in base_keys.items():
if len(keys) > 1 and not keys <= {base, base+'+'}:
raise SystemExit('Incompatible list policies: %r' % keys)
Try / catch
try:
gyp.main(args)
except gyp.input.GypError as e:
if 'Incompatible list policies' in str(e): print('Remove one of the conflicting suffixed keys'); raise Prevention
- Use at most one merge policy per list base (append+prepend is the only allowed pair).
- Avoid mixing bare key with '=' replace.
- Document the suffix semantics for contributors.
When it happens
Trigger: Within one dict being merged, two of {list_base, list_base+'=', list_base+'?', list_base+'+'} that the code marks incompatible coexist. E.g. both 'sources' and 'sources=', or 'sources?' and 'sources+', etc.
Common situations: Copy-pasting sources lists with different suffixes; an include adding 'sources+' while the target already has 'sources='; refactoring that left stale suffixed keys; misunderstanding the suffix semantics.
Related errors
- Attempt to merge list item of unsupported type {item.__class
- Attempt to merge dict value of type {v.__class__.__name__} i
- Attempt to merge dict value of type {v.__class__.__name__} i
- Attempt to merge dict value of unsupported type {v.__class__
- Found wildcard in {dependency_key} of {target} referring to
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/f1bea76c9f6145c2.
Report an issue: GitHub.