{"record":{"id":"a01481a60caf4074","repo":"nodejs/node","slug":"s-while-executing-command-s-in-s","errorCode":null,"errorMessage":"%s while executing command '%s' in %s","messagePattern":"(.+?) while executing command '(.+?)' in (.+?)","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":970,"sourceCode":"                elif command_string:\n                    raise GypError(\n                        \"Unknown command string '%s' in '%s'.\"\n                        % (command_string, contents)\n                    )\n                else:\n                    # Fix up command with platform specific workarounds.\n                    contents = FixupPlatformCommand(contents)\n                    try:\n                        # stderr will be printed no matter what\n                        result = subprocess.run(\n                            contents,\n                            stdout=subprocess.PIPE,\n                            shell=use_shell,\n                            cwd=build_file_dir,\n                            check=False,\n                        )\n                    except Exception as e:\n                        raise GypError(\n                            \"%s while executing command '%s' in %s\"\n                            % (e, contents, build_file)\n                        )\n\n                    if result.returncode > 0:\n                        raise GypError(\n                            \"Call to '%s' returned exit status %d while in %s.\"\n                            % (contents, result.returncode, build_file)\n                        )\n                    replacement = result.stdout.decode(\"utf-8\").rstrip()\n\n                cached_command_results[cache_key] = replacement\n            else:\n                gyp.DebugOutput(\n                    gyp.DEBUG_VARIABLES,\n                    \"Had cache value for command '%s' in directory '%s'\",\n                    contents,\n                    build_file_dir,","sourceCodeStart":952,"sourceCodeEnd":988,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L952-L988","documentation":"When a <!() (or >!) shell-command expansion is evaluated, GYP runs the command via subprocess.run with shell=use_shell and cwd=build_file_dir. If subprocess.run itself raises (e.g. FileNotFoundError because the executable is missing, or a permission error spawning the process), GYP wraps that exception in this GypError, embedding the exception, the command string, and the build file. This is distinct from a non-zero exit code (see error 484).","triggerScenarios":"The command referenced by '<!(foo args)' names an executable not present on PATH; the command string is malformed so the shell cannot spawn; the working directory build_file_dir does not exist or is not readable; the OS refuses to spawn (permissions, OOM, too many fds).","commonSituations":"Forgetting to install a build-time code generator (protoc, gperf, a vendored script); running gyp in an environment without a required tool on PATH; a path with spaces or shell metacharacters breaking the spawn when use_shell is False (array form); a stale build_file_dir after a tree reorganization.","solutions":["Read the embedded exception text — FileNotFoundError means the executable is not on PATH, so install it or fix the path.","If using the array form '<!@[cmd, args]', make sure every element is a real argv entry and the command resolves absolutely.","Verify build_file_dir (the .gyp file's directory) exists and is accessible from gyp's cwd.","Run the exact command string manually from the .gyp file's directory to reproduce the spawn failure."],"exampleFix":"// before — 'my_codegen' not on PATH\n'sources': ['<!(my_codegen --list)'],\n// after — point at the script's real location or install it\n'sources': ['<!(./tools/my_codegen --list)'],","handlingStrategy":"validation","validationCode":"import shutil, os\nfor tool in required_tools:\n    assert shutil.which(tool) or os.path.exists(tool), f'Tool for <() expansion not found: {tool}'","typeGuard":"def is_command_runnable(cmd: str, cwd: str) -> bool:\n    import shutil, os\n    first = shutil._which if False else __import__('shlex').split(cmd)[0]\n    return bool(__import__('shutil').which(first)) and os.path.isdir(cwd or '.')","tryCatchPattern":"try:\n    gyp.process_build_file(...)\nexcept gyp.input.GypError as e:\n    if 'while executing command' in str(e):\n        diagnose_missing_tool(str(e))","preventionTips":["Run each <!() command manually from the .gyp file's directory before committing.","Pin build-time tool versions in the same environment gyp runs in.","Avoid array form '<!@[...]' unless every argv element is real and the executable resolves."],"tags":["gyp","subprocess","command-expansion","environment","build-config"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}