{"record":{"id":"e39761b2c59eebb1","repo":"affaan-m/ECC","slug":"binary-name-must-be-a-non-empty-string","errorCode":null,"errorMessage":"Binary name must be a non-empty string","messagePattern":"Binary name must be a non-empty string","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/package-manager.js","lineNumber":332,"sourceCode":"      return pm.config.devCmd;\n    default:\n      return `${pm.config.runCmd} ${script}`;\n  }\n}\n\n// Allowed characters in arguments: alphanumeric, whitespace, dashes, dots, slashes,\n// equals, colons, commas, quotes, @. Rejects shell metacharacters like ; | & ` $ ( ) { } < > !\nconst SAFE_ARGS_REGEX = /^[@a-zA-Z0-9\\s_./:=,'\"*+-]+$/;\n\n/**\n * Get the command to execute a package binary\n * @param {string} binary - Binary name (e.g., \"prettier\", \"eslint\")\n * @param {string} args - Arguments to pass\n * @throws {Error} If binary name or args contain unsafe characters\n */\nfunction getExecCommand(binary, args = '', options = {}) {\n  if (!binary || typeof binary !== 'string') {\n    throw new Error('Binary name must be a non-empty string');\n  }\n  if (!SAFE_NAME_REGEX.test(binary)) {\n    throw new Error(`Binary name contains unsafe characters: ${binary}`);\n  }\n  if (args && typeof args === 'string' && !SAFE_ARGS_REGEX.test(args)) {\n    throw new Error(`Arguments contain unsafe characters: ${args}`);\n  }\n\n  const pm = getPackageManager(options);\n  return `${pm.config.execCmd} ${binary}${args ? ' ' + args : ''}`;\n}\n\n/**\n * Interactive prompt for package manager selection\n * Returns a message for Claude to show to user\n *\n * NOTE: Does NOT spawn child processes to check availability.\n * Lists all supported PMs and shows how to configure preference.","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/package-manager.js#L314-L350","documentation":"Thrown by getExecCommand() when the `binary` argument is falsy or not a string. getExecCommand builds the package manager's exec command (npx / pnpm dlx / yarn dlx / bunx) for a given binary; this is the first guard ensuring the binary identifier is a usable string before the command is assembled.","triggerScenarios":"Calling getExecCommand(), getExecCommand(undefined), getExecCommand(''), getExecCommand(null), or getExecCommand(42). A caller deriving the binary name from a lookup that returns undefined for an unknown tool.","commonSituations":"A tool-runner that looks up a binary by alias and the alias is missing; a refactor that changes the binary parameter position; passing an object where a string was expected; a config-driven exec where the binary key is absent.","solutions":["Pass a literal binary name: getExecCommand('prettier', '--write .', opts).","Guard the lookup result: if (!binaryName) throw a clearer caller-side error before getExecCommand.","Default to a known binary when the source is optional.","Type-check values read from JSON config before forwarding."],"exampleFix":"// before\nconst cmd = getExecCommand(tool.binName, args, opts); // binName undefined\n\n// after\nconst binName = tool && tool.binName;\nif (!binName) throw new Error(`No binary for tool ${tool && tool.id}`);\nconst cmd = getExecCommand(binName, args, opts);","handlingStrategy":"type-guard","validationCode":"if (!binary || typeof binary !== 'string') {\n  throw new Error('binary name is required');\n}\ngetExecCommand(binary, args, opts);","typeGuard":"function isBinaryName(value) {\n  return typeof value === 'string' && value.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Look up binary names from a fixed catalog before calling.","Guard adapter lookups that may return undefined.","Type-check values read from config files."],"tags":["input-validation","package-manager","shell-injection-guard"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}