nodejs/node · error · ValueError
expected string; got %r
Error message
expected string; got %r
What it means
_String.ValidateMSVS in MSVSSettings.py raises ValueError('expected string; got %r') when the value supplied for an MSVS setting whose declared type is _String is not a Python str. Gyp validates each msvs_settings entry against a type table; the _String type only accepts str, rejecting ints, bools, lists, or None. This guards the gyp -> .vcproj conversion from emitting malformed XML attributes.
Source
Thrown at tools/gyp/pylib/gyp/MSVSSettings.py:110
Args:
value: the MSVS value to convert.
Returns:
the MSBuild equivalent.
Raises:
ValueError if value is not valid.
"""
return value
class _String(_Type):
"""A setting that's just a string."""
def ValidateMSVS(self, value):
if not isinstance(value, str):
raise ValueError("expected string; got %r" % value)
def ValidateMSBuild(self, value):
if not isinstance(value, str):
raise ValueError("expected string; got %r" % value)
def ConvertToMSBuild(self, value):
# Convert the macros
return ConvertVCMacrosToMSBuild(value)
class _StringList(_Type):
"""A settings that's a list of strings."""
def ValidateMSVS(self, value):
if not isinstance(value, (list, str)):
raise ValueError("expected string list; got %r" % value)
def ValidateMSBuild(self, value):View on GitHub (pinned to 1b2de5e052)
Solutions
- Inspect the named setting in the failing msvs_settings dict and coerce the value to str: str(value).
- Match the documented MSVS value format (e.g. Optimization expects "0"/"1"/"2"/"3"/"4" as strings, not ints).
- If the value is genuinely optional, omit the key instead of passing None.
- Run gyp with --debug general to see which target/setting triggered the validator.
Example fix
# before 'Optimization': 2, # after 'Optimization': '2',
Defensive patterns
Strategy: type-guard
Validate before calling
def coerce_string_setting(value):
if value is None:
return None # caller should omit key
if not isinstance(value, str):
raise TypeError('MSVS string setting expects str, got %r' % type(value))
return value Type guard
def is_msvs_string(value) -> bool:
return isinstance(value, str) Try / catch
try:
_string.ValidateMSVS(my_value)
except ValueError:
my_value = str(my_value) # or omit the setting
_string.ValidateMSVS(my_value) Prevention
- Quote all MSVS string settings in .gyp files; never rely on implicit int->str.
- For optional settings, omit the key rather than passing None.
- Run gyp with --debug general to surface the failing setting name quickly.
When it happens
Trigger: A gyp file sets an MSVS string setting to a non-string YAML/JSON-like value, e.g. 'Optimization': 2 (int) or 'AdditionalIncludeDirectories': None; the msvs_settings dict is assembled programmatically and a number slips through where the schema expects a string macro like "$(IntDir)".
Common situations: Migrating a .gyp from another generator (make/ninja) where ints were tolerated; copy-pasting MSBuild-style boolean True/False into an MSVS-only setting; downstream tooling that emits numeric optimization levels.
Related errors
- expected string list; got %r
- expected bool; got %r
- AddFileConfig: file "%s" not in project.
- unrecognized enumerated value %s
- index value (%d) not in expected range [0, %d)
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/fec26c90ba3a87ef.
Report an issue: GitHub.