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_base

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Keep at most one merge policy per list base within a single dict (append and prepend are the only pair that may coexist).
  2. Remove the redundant/contradictory suffixed key.
  3. 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

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


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