nodejs/node · error · TypeError

Appending "%s" to a non-list setting "%s" for tool "%s" is n

Error message

Appending "%s" to a non-list setting "%s" for tool "%s" is not allowed, previous value: %s

What it means

Raised as a TypeError by the MSVS tool-setting merge helper when an 'append' operation would combine an existing setting value and a new value where at least one is not a list. The merge only auto-concatenates when both the stored value and the incoming value are lists; any scalar-vs-list mismatch is rejected to avoid silent data corruption of project settings.

Source

Thrown at tools/gyp/pylib/gyp/generator/msvs.py:293

def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False):
    # TODO(bradnelson): ugly hack, fix this more generally!!!
    if "Directories" in setting or "Dependencies" in setting:
        if isinstance(value, str):
            value = value.replace("/", "\\")
        else:
            value = [i.replace("/", "\\") for i in value]
    if not tools.get(tool_name):
        tools[tool_name] = {}
    tool = tools[tool_name]
    if setting == "CompileAsWinRT":
        return
    if tool.get(setting):
        if only_if_unset:
            return
        if isinstance(tool[setting], list) and isinstance(value, list):
            tool[setting] += value
        else:
            raise TypeError(
                'Appending "%s" to a non-list setting "%s" for tool "%s" is '
                "not allowed, previous value: %s"
                % (value, setting, tool_name, str(tool[setting]))
            )
    else:
        tool[setting] = value


def _ConfigTargetVersion(config_data):
    return config_data.get("msvs_target_version", "Windows7")


def _ConfigPlatform(config_data):
    return config_data.get("msvs_configuration_platform", "Win32")


def _ConfigBaseName(config_name, platform_name):
    if config_name.endswith("_" + platform_name):

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Make the setting a list in both the original definition and the appended value so both are lists.
  2. Audit the target's msvs_settings and any included .gypi for the offending setting name (shown in the message) and unify its value type.
  3. If a scalar is intended, replace the append with a direct set (only_if_unset path) instead of an append.

Example fix

// before — one place scalar, another appends a list
'msvs_settings': { 'VCLinkerTool': { 'AdditionalDependencies': 'foo.lib' } }
// ...later append of ['bar.lib'] fails
// after — use a list consistently
'msvs_settings': { 'VCLinkerTool': { 'AdditionalDependencies': ['foo.lib'] } }
Defensive patterns

Strategy: validation

Validate before calling

def safe_append(existing, new):
    if existing is None:
        return new
    if isinstance(existing, list) and isinstance(new, list):
        return existing + new
    raise TypeError(f'cannot append {type(new)} to {type(existing)}')

Type guard

def both_lists(a, b) -> bool:
    return isinstance(a, list) and isinstance(b, list)

Try / catch

try:
    _MergeToolSetting(tools, tool_name, setting, value, only_if_unset)
except TypeError as e:
    if 'non-list setting' in str(e):
        coerce_setting_to_list(tools, tool_name, setting)
    raise

Prevention

When it happens

Trigger: During MSVS project generation, merging tool settings where a setting already has a scalar (string) value and a list value is appended, or vice versa. Triggered inside the helper that processes msvs_settings/tool settings at msvs.py:289 when `isinstance(tool[setting], list) and isinstance(value, list)` is False but tool[setting] is already set and only_if_unset is False.

Common situations: A .gyp target sets an MSVS tool setting as a string in one place and another rule/condition appends a list to the same setting; mixing 'msvs_settings' overrides where one defines a scalar and another appends; conditional settings that change a field's effective type across configurations.

Related errors


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