{"record":{"id":"8a2d7f3ef48099ba","repo":"nodejs/node","slug":"expected-string-list-got-r","errorCode":null,"errorMessage":"expected string list; got %r","messagePattern":"expected string list; got %r","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/MSVSSettings.py","lineNumber":126,"sourceCode":"    def ValidateMSVS(self, value):\n        if not isinstance(value, str):\n            raise ValueError(\"expected string; got %r\" % value)\n\n    def ValidateMSBuild(self, value):\n        if not isinstance(value, str):\n            raise ValueError(\"expected string; got %r\" % value)\n\n    def ConvertToMSBuild(self, value):\n        # Convert the macros\n        return ConvertVCMacrosToMSBuild(value)\n\n\nclass _StringList(_Type):\n    \"\"\"A settings that's a list of strings.\"\"\"\n\n    def ValidateMSVS(self, value):\n        if not isinstance(value, (list, str)):\n            raise ValueError(\"expected string list; got %r\" % value)\n\n    def ValidateMSBuild(self, value):\n        if not isinstance(value, (list, str)):\n            raise ValueError(\"expected string list; got %r\" % value)\n\n    def ConvertToMSBuild(self, value):\n        # Convert the macros\n        if isinstance(value, list):\n            return [ConvertVCMacrosToMSBuild(i) for i in value]\n        else:\n            return ConvertVCMacrosToMSBuild(value)\n\n\nclass _Boolean(_Type):\n    \"\"\"Boolean settings, can have the values 'false' or 'true'.\"\"\"\n\n    def _Validate(self, value):\n        if value not in {\"true\", \"false\"}:","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/MSVSSettings.py#L108-L144","documentation":"_StringList.ValidateMSVS raises ValueError('expected string list; got %r') when the value for an MSVS list-typed setting is neither a list nor a str. List settings (e.g. AdditionalIncludeDirectories, PreprocessorDefinitions) accept either a Python list of strings or a single string; anything else (int, dict, None, nested list) is rejected.","triggerScenarios":"Setting a list-type MSVS setting to an int/None/dict; passing a semicolon-separated string is fine, but passing a non-string scalar is not.","commonSituations":"Refactor that turned a list literal into a single computed value without wrapping it in [ ]; templating code that sometimes yields None for an optional include dir.","solutions":["Wrap the value in a list: [value] if it is a single string, or ensure it is already a list.","Omit the setting entirely when it would be None rather than passing None.","Confirm the setting is registered as _StringList in MSVSSettings and supply the expected shape."],"exampleFix":"# before\n'AdditionalIncludeDirectories': INC_DIR,  # INC_DIR is int or None\n\n# after\n'AdditionalIncludeDirectories': [str(INC_DIR)] if INC_DIR else [],","handlingStrategy":"type-guard","validationCode":"def coerce_string_list(value):\n    if value is None:\n        return []\n    if isinstance(value, str):\n        return [value]\n    if isinstance(value, list):\n        if not all(isinstance(i, str) for i in value):\n            raise TypeError('list items must be str')\n        return value\n    raise TypeError('expected str or list of str, got %r' % type(value))","typeGuard":"def is_string_list(value) -> bool:\n    return isinstance(value, str) or (isinstance(value, list) and all(isinstance(i, str) for i in value))","tryCatchPattern":"try:\n    _file_list.ValidateMSVS(my_list)\nexcept ValueError:\n    my_list = coerce_string_list(my_list)\n    _file_list.ValidateMSVS(my_list)","preventionTips":["Wrap scalar strings in [ ] when a setting is list-typed to be explicit.","Return [] from templates for optional list settings instead of None.","Keep a single helper that normalizes list/str -> list[str] for all list settings."],"tags":["gyp","msvs","validation","type-check","list"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}