{"record":{"id":"1cdf3cf02f730126","repo":"nodejs/node","slug":"the-run-as-in-target-s-from-file-s-should-be-a","errorCode":null,"errorMessage":"The 'run_as' in target %s from file %s should be a dictionary.","messagePattern":"The 'run_as' in target (.+?) from file (.+?) should be a dictionary\\.","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":2776,"sourceCode":"        for source_key in source_keys:\n            for source in target_dict.get(source_key, []):\n                (_source_root, source_extension) = os.path.splitext(source)\n                if source_extension.startswith(\".\"):\n                    source_extension = source_extension[1:]\n                if source_extension == rule_extension:\n                    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 \"","sourceCodeStart":2758,"sourceCodeEnd":2794,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L2758-L2794","documentation":"ValidateRunAsInTarget requires that, when present, the 'run_as' key of a target be a dict mapping fields like 'action'/'working_directory'/'environment'. A non-dict (typically a list or string) is rejected before any field is read, because the subsequent .get() calls would fail or misbehave.","triggerScenarios":"target_dict['run_as'] is truthy but isinstance(run_as, dict) is False.","commonSituations":"Writing run_as as a bare command string or as a list mimicking 'action' directly, instead of wrapping it in a dict; copy-paste from an 'actions' entry where the list form is valid.","solutions":["Wrap the run_as value in a dict.","Put the command under an 'action' key inside that dict.","Re-run gyp."],"exampleFix":"// before\n'run_as': ['my_app', '--flag'],\n// after\n'run_as': { 'action': ['my_app', '--flag'] },","handlingStrategy":"type-guard","validationCode":"ra = target_dict.get('run_as')\nif ra is not None and not isinstance(ra, dict):\n    raise TypeError('run_as must be a dict')","typeGuard":"def run_as_is_dict(target_dict: dict) -> bool:\n    ra = target_dict.get('run_as')\n    return ra is None or isinstance(ra, dict)","tryCatchPattern":null,"preventionTips":["Model run_as as a dict with action/working_directory/environment keys only.","Do not reuse the 'actions' list shape for run_as.","Validate .gyp files with a JSON-schema-like check before invoking gyp."],"tags":["gyp","run-as","type","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}