nodejs/node · error · ValueError

expected bool; got %r

Error message

expected bool; got %r

What it means

_Boolean._Validate raises ValueError('expected bool; got %r') when a boolean-typed MSVS/MSBuild setting is given a value that is not exactly the string 'true' or 'false'. Note these are the lowercase strings, not Python bools (True/False) and not 'True'/'False'. Gyp stores booleans as those literal strings because they map directly to MSBuild XML attribute values.

Source

Thrown at tools/gyp/pylib/gyp/MSVSSettings.py:145

    def ValidateMSBuild(self, value):
        if not isinstance(value, (list, str)):
            raise ValueError("expected string list; got %r" % value)

    def ConvertToMSBuild(self, value):
        # Convert the macros
        if isinstance(value, list):
            return [ConvertVCMacrosToMSBuild(i) for i in value]
        else:
            return ConvertVCMacrosToMSBuild(value)


class _Boolean(_Type):
    """Boolean settings, can have the values 'false' or 'true'."""

    def _Validate(self, value):
        if value not in {"true", "false"}:
            raise ValueError("expected bool; got %r" % value)

    def ValidateMSVS(self, value):
        self._Validate(value)

    def ValidateMSBuild(self, value):
        self._Validate(value)

    def ConvertToMSBuild(self, value):
        self._Validate(value)
        return value


class _Integer(_Type):
    """Integer settings."""

    def __init__(self, msbuild_base=10):
        _Type.__init__(self)
        self._msbuild_base = msbuild_base

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Use the lowercase string literals 'true' or 'false' in the setting value.
  2. If computing the value, map it explicitly: 'true' if flag else 'false'.
  3. Audit the setting name in MSVSSettings to confirm it is registered as _Boolean.

Example fix

# before
'GenerateManifest': True,

# after
'GenerateManifest': 'true',
Defensive patterns

Strategy: type-guard

Validate before calling

def to_msvs_bool(value):
    if isinstance(value, bool):
        return 'true' if value else 'false'
    if value in ('true', 'false'):
        return value
    raise ValueError('expected true/false, got %r' % value)

Type guard

def is_msvs_bool_string(value) -> bool:
    return value in ('true', 'false')

Try / catch

try:
    _boolean.ValidateMSBuild(my_flag)
except ValueError:
    my_flag = to_msvs_bool(my_flag)
    _boolean.ValidateMSBuild(my_flag)

Prevention

When it happens

Trigger: Passing Python True/False (bool), 1/0 (int), 'True'/'False' (wrong case), or 'yes'/'no' to a setting registered as _Boolean.

Common situations: Developers writing gyp files instinctively use Python True/False; copying values from documentation that capitalizes them; converting from a system that uses 0/1.

Related errors


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