{"record":{"id":"e96a9199dddb5e8b","repo":"nodejs/node","slug":"s-s-must-be-at-least-length-2-not-s","errorCode":null,"errorMessage":"%s %s must be at least length 2, not %s","messagePattern":"(.+?) (.+?) must be at least length 2, not (.+?)","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":1120,"sourceCode":"        output = int(output)\n\n    return output\n\n\n# The same condition is often evaluated over and over again so it\n# makes sense to cache as much as possible between evaluations.\ncached_conditions_asts = {}\n\n\ndef EvalCondition(condition, conditions_key, phase, variables, build_file):\n    \"\"\"Returns the dict that should be used or None if the result was\n    that nothing should be used.\"\"\"\n    if not isinstance(condition, list):\n        raise GypError(conditions_key + \" must be a list\")\n    if len(condition) < 2:\n        # It's possible that condition[0] won't work in which case this\n        # attempt will raise its own IndexError.  That's probably fine.\n        raise GypError(\n            conditions_key\n            + \" \"\n            + condition[0]\n            + \" must be at least length 2, not \"\n            + str(len(condition))\n        )\n\n    i = 0\n    result = None\n    while i < len(condition):\n        cond_expr = condition[i]\n        true_dict = condition[i + 1]\n        if not isinstance(true_dict, dict):\n            raise GypError(\n                f\"{conditions_key} {cond_expr} must be followed by a dictionary, \"\n                f\"not {type(true_dict)}\"\n            )\n        if len(condition) > i + 2 and isinstance(condition[i + 2], dict):","sourceCodeStart":1102,"sourceCodeEnd":1138,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L1102-L1138","documentation":"Each condition entry must have at least two elements — a cond_expr and a true_dict — so that EvalCondition can index condition[0] and condition[1]. If len(condition) < 2 (e.g. an empty list or a lone expression with no body), GYP raises this GypError, embedding the (possibly empty) condition[0] and the actual length. Note the code comment: if condition[0] itself raises IndexError on an empty list, that bubbles up — also a sign of the same root cause.","triggerScenarios":"Writing \"'conditions': [ ['OS==\\\"mac\\\"'] ]\" with no dict body; an empty condition list \"'conditions': [ [] ]\"; a generator that emits only the expression half.","commonSituations":"Truncated copy-paste of a condition; deleting the true_dict during editing and forgetting to restore it; templating that drops the body when a variable is empty.","solutions":["Add the required second element — a dict merged in when the condition is true.","If the condition is intentionally a no-op, remove the whole entry rather than leaving a 1-element list.","Optionally add a third dict (false_dict) for the else branch."],"exampleFix":"// before\n'conditions': [ ['OS == \"mac\"'] ],\n// after\n'conditions': [ ['OS == \"mac\"', { 'defines': ['IS_MAC'] }] ],","handlingStrategy":"validation","validationCode":"def validate_condition(entry, key='conditions'):\n    assert isinstance(entry, list) and len(entry) >= 2, \\\n        f'{key} entry {entry!r} must have at least [expr, true_dict]'","typeGuard":"def has_min_length_two(entry) -> bool:\n    return isinstance(entry, list) and len(entry) >= 2","tryCatchPattern":null,"preventionTips":["Always include a true_dict body for each condition expression.","If a condition is not needed, delete the whole entry.","Use a structural linter that flags short condition lists."],"tags":["gyp","conditions","syntax","build-config"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}