jackwener/OpenCLI · error
Install command is empty.
Error message
Install command is empty.
What it means
parseCommand throws when tokenising the command yields zero tokens — i.e. the command string contains no actual words (empty or whitespace/quotes only). The library cannot determine a binary to run, so it fails fast.
Source
Thrown at src/external.ts:130
export function parseCommand(cmd: string): { binary: string; args: string[] } {
const shellOperators = /&&|\|\|?|;|[><`$#\n\r]|\$\(/;
if (shellOperators.test(cmd)) {
throw new Error(
`Install command contains unsafe shell operators and cannot be executed securely: "${cmd}". ` +
`Please install the tool manually.`
);
}
// Tokenise respecting single- and double-quoted segments (no variable expansion).
const tokens: string[] = [];
const re = /(?:"([^"]*)")|(?:'([^']*)')|(\S+)/g;
let match: RegExpExecArray | null;
while ((match = re.exec(cmd)) !== null) {
tokens.push(match[1] ?? match[2] ?? match[3]);
}
if (tokens.length === 0) {
throw new Error(`Install command is empty.`);
}
const [binary, ...args] = tokens;
return { binary, args };
}
function shouldRetryWithCmdShim(binary: string, err: unknown): boolean {
const code = err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;
return os.platform() === 'win32' && !path.extname(binary) && code === 'ENOENT';
}
function runInstallCommand(cmd: string): void {
const { binary, args } = parseCommand(cmd);
try {
execFileSync(binary, args, { stdio: 'inherit' });
} catch (err) {
if (shouldRetryWithCmdShim(binary, err)) {View on GitHub (pinned to 49907e53dc)
Solutions
- Provide a non-empty install command (e.g. 'npm install -g <tool>') in the config.
- Trim whitespace before saving/loading the config value to avoid whitespace-only strings.
- If the tool cannot be auto-installed, install it manually so no install command is needed.
Example fix
// before (apps.yaml) install: " " // after install: "npm install -g mytool"
Defensive patterns
Strategy: validation
Validate before calling
if (!cmd || cmd.trim().length === 0) {
throw new Error("Install command must be a non-empty string before calling parseCommand");
}
parseCommand(cmd); Type guard
function isNonEmptyCommand(cmd: unknown): cmd is string {
return typeof cmd === "string" && cmd.trim().length > 0;
} Try / catch
try {
const { binary } = parseCommand(cmd);
} catch (e) {
if (e.message === "Install command is empty.") {
console.error("No install command configured; install the tool manually.");
}
} Prevention
- Validate installCommand is non-empty when loading config files.
- Use YAML/schema validation (e.g. zod) requiring min length 1 on install fields.
- Trim values before saving them to config.
When it happens
Trigger: Calling parseCommand(''), parseCommand(' '), or a string of only quote characters; any install command whose tokenizer regex matches nothing.
Common situations: Empty installCommand field in apps.yaml or CLI registry config; config value that is only spaces; a template placeholder (${...}) that was stripped earlier by the shell-operator check leaving an empty string.
Related errors
- ${label} cannot be empty
- ${label} cannot be empty
- ${label} cannot be empty
- Not a username: "${raw}"
- pubmed ${label} cannot be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5c7ea65ad98e5894.
Report an issue: GitHub.