{"record":{"id":"21d9500d334ff7e1","repo":"nodejs/node","slug":"not-enough-arguments-21d950","errorCode":null,"errorMessage":"Not enough arguments","messagePattern":"Not enough arguments","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/mac_tool.py","lineNumber":38,"sourceCode":"import subprocess\nimport sys\nimport tempfile\n\n\ndef main(args):\n    executor = MacTool()\n    if (exit_code := executor.Dispatch(args)) is not None:\n        sys.exit(exit_code)\n\n\nclass MacTool:\n    \"\"\"This class performs all the Mac tooling steps. The methods can either be\n    executed directly, or dispatched from an argument list.\"\"\"\n\n    def Dispatch(self, args):\n        \"\"\"Dispatches a string command to a method.\"\"\"\n        if len(args) < 1:\n            raise Exception(\"Not enough arguments\")\n\n        method = \"Exec%s\" % self._CommandifyName(args[0])\n        return getattr(self, method)(*args[1:])\n\n    def _CommandifyName(self, name_string):\n        \"\"\"Transforms a tool name like copy-info-plist to CopyInfoPlist\"\"\"\n        return name_string.title().replace(\"-\", \"\")\n\n    def ExecCopyBundleResource(self, source, dest, convert_to_binary):\n        \"\"\"Copies a resource file to the bundle/Resources directory, performing any\n        necessary compilation on each resource.\"\"\"\n        convert_to_binary = convert_to_binary == \"True\"\n        extension = os.path.splitext(source)[1].lower()\n        if os.path.isdir(source):\n            # Copy tree.\n            # TODO(thakis): This copies file attributes like mtime, while the\n            # single-file branch below doesn't. This should probably be changed to\n            # be consistent with the single-file branch.","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/mac_tool.py#L20-L56","documentation":"mac_tool.py's MacTool.Dispatch expects argv-style args whose first element names the subcommand (e.g. 'copy-bundle-resource'). It maps that name to an Exec<Name> method. With an empty args list there is no subcommand to dispatch, so it raises a plain Exception.","triggerScenarios":"MacTool.Dispatch is called with an empty list/tuple (len(args) < 1). This is normally driven by the gyp-mac-tool wrapper invoked from the Makefile generator.","commonSituations":"A broken Makefile/gyp rule that invokes 'gyp-mac-tool' with no arguments; calling MacTool().Dispatch([]) directly in a test; argument quoting bug that swallowed the subcommand.","solutions":["Inspect the generated Makefile rule and confirm the mac-tool invocation includes the subcommand token.","If invoking MacTool directly, pass the subcommand name as args[0].","Regenerate the project with gyp so the Makefile rule is rewritten correctly."],"exampleFix":"// before\n$ python mac_tool.py\n# or MacTool().Dispatch([])\n// after\n$ python mac_tool.py copy-bundle-resource src.png out.png True\n# or MacTool().Dispatch(['copy-bundle-resource', 'src.png', 'out.png', 'True'])","handlingStrategy":"validation","validationCode":"# If invoking MacTool directly, guard the dispatch.\nif not args:\n    raise SystemExit('usage: mac_tool.py <subcommand> [args...]')\nexecutor.Dispatch(args)","typeGuard":"def has_subcommand(args) -> bool:\n    return isinstance(args, (list, tuple)) and len(args) >= 1 and bool(args[0])","tryCatchPattern":"try:\n    executor.Dispatch(args)\nexcept Exception as e:\n    if 'Not enough arguments' in str(e):\n        sys.stderr.write('usage: mac_tool.py <subcommand> [args...]\\n')\n        sys.exit(2)\n    raise","preventionTips":["Never call gyp-mac-tool without a subcommand; the Makefile rule should always include one.","In tests, always pass the subcommand name as the first arg.","If the rule is missing the token, regenerate the project with gyp."],"tags":["gyp","mac","mac-tool","arguments"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}