nodejs/node · error · ValueError

index value (%d) not in expected range [0, %d)

Error message

index value (%d) not in expected range [0, %d)

What it means

_Enumeration.ConvertToMSBuild raises ValueError('index value (%d) not in expected range [0, %d)') when an MSVS enumeration is supplied as an integer index that is negative or >= the length of the enumeration's _label_list. The MSVS side stores enumerations as integer indices; ConvertToMSBuild maps each index to a label. An out-of-range index means the source gyp value does not correspond to any known option.

Source

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

    def __init__(self, label_list, new=None):
        _Type.__init__(self)
        self._label_list = label_list
        self._msbuild_values = {value for value in label_list if value is not None}
        if new is not None:
            self._msbuild_values.update(new)

    def ValidateMSVS(self, value):
        # Try to convert.  It will raise an exception if not valid.
        self.ConvertToMSBuild(value)

    def ValidateMSBuild(self, value):
        if value not in self._msbuild_values:
            raise ValueError("unrecognized enumerated value %s" % value)

    def ConvertToMSBuild(self, value):
        index = int(value)
        if index < 0 or index >= len(self._label_list):
            raise ValueError(
                "index value (%d) not in expected range [0, %d)"
                % (index, len(self._label_list))
            )
        label = self._label_list[index]
        if label is None:
            raise ValueError("converted value for %s not specified." % value)
        return label


# Instantiate the various generic types.
_boolean = _Boolean()
_integer = _Integer()
# For now, we don't do any special validation on these types:
_string = _String()
_file_name = _String()
_folder_name = _String()
_file_list = _StringList()
_folder_list = _StringList()

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Open MSVSSettings.py, find the setting's _Enumeration([...]) definition, and use an index within [0, len(labels)).
  2. Prefer the MSBuild label string form to avoid index arithmetic entirely.
  3. Bound the computed index: index = max(0, min(index, len(labels) - 1)).

Example fix

# before
# _Enumeration(['Disabled','MinSpace','MinSize','Full','MaxSpeed']) -> indices 0..4
'Optimization': '5',

# after
'Optimization': '4',   # 'MaxSpeed'
Defensive patterns

Strategy: validation

Validate before calling

def clamp_index(index, label_list):
    i = int(index)
    if i < 0 or i >= len(label_list):
        raise ValueError('index %d out of range [0,%d)' % (i, len(label_list)))
    return i

Type guard

def is_in_range_index(value, label_list) -> bool:
    try:
        return 0 <= int(value) < len(label_list)
    except (TypeError, ValueError):
        return False

Try / catch

try:
    enum_type.ConvertToMSBuild(my_value)
except ValueError:
    my_value = str(min(max(int(my_value), 0), len(enum_type._label_list) - 1))
    enum_type.ConvertToMSBuild(my_value)

Prevention

When it happens

Trigger: Setting an MSVS enumeration to an integer (or numeric string) outside the supported range, e.g. 'Optimization': '5' when only indices 0..4 are defined; computing an index dynamically and going off the end.

Common situations: Hardcoding a numeric value copied from an old VS version whose enumeration had more entries; off-by-one when deriving the index from a list lookup.

Related errors


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