{"record":{"id":"60282fbac6a94927","repo":"nodejs/node","slug":"the-run-as-in-target-s-from-file-s-must-have-a","errorCode":null,"errorMessage":"The 'run_as' in target %s from file %s must have an 'action' section.","messagePattern":"The 'run_as' in target (.+?) from file (.+?) must have an 'action' section\\.","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":2782,"sourceCode":"                    rule_sources.append(source)\n\n        if len(rule_sources) > 0:\n            rule[\"rule_sources\"] = rule_sources\n\n\ndef ValidateRunAsInTarget(target, target_dict, build_file):\n    target_name = target_dict.get(\"target_name\")\n    run_as = target_dict.get(\"run_as\")\n    if not run_as:\n        return\n    if not isinstance(run_as, dict):\n        raise GypError(\n            \"The 'run_as' in target %s from file %s should be a \"\n            \"dictionary.\" % (target_name, build_file)\n        )\n    action = run_as.get(\"action\")\n    if not action:\n        raise GypError(\n            \"The 'run_as' in target %s from file %s must have an \"\n            \"'action' section.\" % (target_name, build_file)\n        )\n    if not isinstance(action, list):\n        raise GypError(\n            \"The 'action' for 'run_as' in target %s from file %s \"\n            \"must be a list.\" % (target_name, build_file)\n        )\n    working_directory = run_as.get(\"working_directory\")\n    if working_directory and not isinstance(working_directory, str):\n        raise GypError(\n            \"The 'working_directory' for 'run_as' in target %s \"\n            \"in file %s should be a string.\" % (target_name, build_file)\n        )\n    environment = run_as.get(\"environment\")\n    if environment and not isinstance(environment, dict):\n        raise GypError(\n            \"The 'environment' for 'run_as' in target %s \"","sourceCodeStart":2764,"sourceCodeEnd":2800,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L2764-L2800","documentation":"After confirming run_as is a dict, ValidateRunAsInTarget reads its 'action' field and treats a missing or empty value as invalid, because a run_as entry with nothing to execute has no purpose.","triggerScenarios":"target_dict['run_as'] is a dict but run_as.get('action') returns None or a falsy value (empty list/string).","commonSituations":"Adding run_as with only working_directory/environment set and forgetting action; renaming the key; typos like 'actions' instead of 'action'.","solutions":["Add an 'action' key to the run_as dict whose value is a non-empty list of command arguments.","Check for typos in the key name ('action' vs 'actions'/'command').","Re-run gyp."],"exampleFix":"// before\n'run_as': { 'working_directory': '<(PRODUCT_DIR)' },\n// after\n'run_as': { 'action': ['<(PRODUCT_DIR)/my_app'], 'working_directory': '<(PRODUCT_DIR)' },","handlingStrategy":"validation","validationCode":"ra = target_dict.get('run_as')\nif isinstance(ra, dict) and not ra.get('action'):\n    raise ValueError('run_as.action is required and must be non-empty')","typeGuard":"def run_as_has_action(target_dict: dict) -> bool:\n    ra = target_dict.get('run_as')\n    return ra is None or (isinstance(ra, dict) and bool(ra.get('action')))","tryCatchPattern":null,"preventionTips":["Always author run_as with an 'action' key, even in early drafts.","Distinguish 'action' (run_as) from 'actions' (target-level) — different concepts."],"tags":["gyp","run-as","required-field","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}