nodejs/node · error · ValueError

value must be one of [0, 1, 2]; got %s

Error message

value must be one of [0, 1, 2]; got %s

What it means

A bespoke _Translate function for the VS 'PreprocessToFile/PreprocessSuppressLineNumbers' setting raises ValueError('value must be one of [0, 1, 2]; got %s') when the preprocess level is anything other than the literal strings '0', '1', or '2'. These map to: 0 = no preprocessing, 1 = /P (preprocess to file, keep line numbers), 2 = /EP /P (preprocess, strip line numbers). A dummy _Enumeration(['a','b','c']) is used as the MSVS validator only to accept indices 0..2, but the actual conversion enforces the string forms.

Source

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

    _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS
    _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate


def _CustomGeneratePreprocessedFile(tool, msvs_name):
    def _Translate(value, msbuild_settings):
        tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
        if value == "0":
            tool_settings["PreprocessToFile"] = "false"
            tool_settings["PreprocessSuppressLineNumbers"] = "false"
        elif value == "1":  # /P
            tool_settings["PreprocessToFile"] = "true"
            tool_settings["PreprocessSuppressLineNumbers"] = "false"
        elif value == "2":  # /EP /P
            tool_settings["PreprocessToFile"] = "true"
            tool_settings["PreprocessSuppressLineNumbers"] = "true"
        else:
            raise ValueError("value must be one of [0, 1, 2]; got %s" % value)

    # Create a bogus validator that looks for '0', '1', or '2'
    msvs_validator = _Enumeration(["a", "b", "c"]).ValidateMSVS
    _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator
    msbuild_validator = _boolean.ValidateMSBuild
    msbuild_tool_validators = _msbuild_validators[tool.msbuild_name]
    msbuild_tool_validators["PreprocessToFile"] = msbuild_validator
    msbuild_tool_validators["PreprocessSuppressLineNumbers"] = msbuild_validator
    _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate


fix_vc_macro_slashes_regex_list = ("IntDir", "OutDir")
fix_vc_macro_slashes_regex = re.compile(
    r"(\$\((?:%s)\))(?:[\\/]+)" % "|".join(fix_vc_macro_slashes_regex_list)
)

# Regular expression to detect keys that were generated by exclusion lists
_EXCLUDED_SUFFIX_RE = re.compile("^(.*)_excluded$")

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Use exactly one of the strings '0', '1', or '2'.
  2. If the value is computed as an int, str() it and clamp to {0,1,2}.
  3. Verify the setting name against the registration block in MSVSSettings.py around line 363.

Example fix

# before
preprocess_level = 1   # int -> fails

# after
preprocess_level = '1'
Defensive patterns

Strategy: validation

Validate before calling

def coerce_preprocess_level(value):
    s = str(value)
    if s not in ('0', '1', '2'):
        raise ValueError('preprocess level must be 0/1/2, got %r' % value)
    return s

Type guard

def is_valid_preprocess_level(value) -> bool:
    return str(value) in ('0', '1', '2')

Try / catch

try:
    _Translate(my_value, msbuild_settings)
except ValueError:
    my_value = coerce_preprocess_level(my_value)
    _Translate(my_value, msbuild_settings)

Prevention

When it happens

Trigger: Setting the preprocess setting to an integer 0/1/2 (Python int, not string), to '3', or to any out-of-set string; relying on the dummy enumeration validator without realizing the converter re-checks.

Common situations: Programmatically assigning an int instead of '0'/'1'/'2'; copy-pasting 'yes'/'no'; misreading the dummy enumeration as accepting arbitrary values.

Related errors


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