affaan-m/ECC · error · Error
Executable must be one argv entry, not an interpolated…
Error message
Executable must be one argv entry, not an interpolated shell command string.
What it means
validateExecutable rejects values that look like an interpolated shell command string (contain whitespace but don't resemble a path) to enforce that --executable is exactly one argv entry. The script spawns the executable directly without a shell, so 'wezterm start --cwd x' as one string would be interpreted as a single program name and silently fail or be a shell-injection vector.
Solutions
- Split the command: pass only the program in --executable and the remaining words as arguments after `--`.
- If you truly mean a path-like value, use an absolute path containing `/` before any whitespace (e.g. `/usr/local/bin/my exe` quoted).
- Avoid shell metacharacters and interpolation; construct argv arrays programmatically instead of strings.
Example fix
// before node open-terminal.js --executable "wezterm start --always-new-process" // after node open-terminal.js --executable wezterm -- start --always-new-process
Defensive patterns
Strategy: validation
Validate before calling
if (typeof exe === 'string' && /\s/.test(exe) && !exe.includes('/') && !require('path').isAbsolute(exe)) {
throw new Error('split the command: pass program via --executable and args after --');
} Type guard
function isSingleArgvProgram(v) {
if (typeof v !== 'string' || !v.trim()) return false;
const ws = v.search(/\s/);
const sep = Math.min(...['/', '\\'].map(c => v.indexOf(c)).filter(i => i >= 0), Infinity);
if (ws < 0) return true;
return require('path').isAbsolute(v) || (sep !== Infinity && sep < ws);
} Try / catch
try {
parseArgs(process.argv);
} catch (e) {
if (/one argv entry/.test(e.message)) {
console.error('Put extra words after -- instead of embedding them in --executable');
} else throw e;
} Prevention
- Build argv arrays, never interpolated command strings.
- Keep the program in --executable and arguments after `--`.
- Lint scripts for string-concatenated commands.
- Educate users that the tool spawns without a shell.
When it happens
Trigger: Passing `--executable "wezterm start"` or `--executable "sh -c 'ls'"` — strings with spaces that aren't absolute/multi-segment paths.
Common situations: Users copying a full shell command line into --executable; scripts interpolating multiple args into one string instead of splitting them into separate argv entries after `--`.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Arguments must not contain NUL bytes.
- Executable must be a non-empty argv entry without control…
- all overlays must be readable local files
- all takes must be readable local files
- asset name must be a simple filename stem (letters, digits…
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/e442133f5c619368.
Report an issue: GitHub.
Appendix: source
Thrown at skills/terminal-opener/scripts/open-terminal.js:63
function validateCwd(value) {
if (value.includes('\0')) throw new Error('--cwd must not contain a NUL byte.');
if (!isAbsolutePath(value)) throw new Error('--cwd must be an absolute path.');
}
function validateExecutable(value) {
if (!value || /[\0\r\n]/.test(value)) {
throw new Error('Executable must be a non-empty argv entry without control bytes.');
}
const whitespaceIndex = value.search(/\s/);
const separatorIndexes = [value.indexOf('/'), value.indexOf('\\')].filter(index => index >= 0);
const firstSeparatorIndex = separatorIndexes.length > 0 ? Math.min(...separatorIndexes) : -1;
const resemblesExecutablePath = isAbsolutePath(value)
|| (firstSeparatorIndex >= 0 && (whitespaceIndex < 0 || firstSeparatorIndex < whitespaceIndex));
if (whitespaceIndex >= 0 && !resemblesExecutablePath) {
throw new Error(
'Executable must be one argv entry, not an interpolated shell command string.'
);
}
if (!resemblesExecutablePath && /[;&|<>`$]/.test(value)) {
throw new Error(
'Executable must be one argv entry, not an interpolated shell command string.'
);
}
}
function validateArgv(argv) {
for (const argument of argv) {
if (argument.includes('\0')) throw new Error('Arguments must not contain NUL bytes.');
}
}
function readValue(argv, index, option) {
const value = argv[index + 1];View on GitHub (pinned to 8321021c54)