affaan-m/ECC · error · Error
Executable must be a non-empty argv entry without control by
Error message
Executable must be a non-empty argv entry without control bytes.
What it means
validateExecutable rejects an empty executable or one containing NUL (\0), CR (\r), or LF (\n) control bytes. These would break argv handling or enable line-splitting injection. This is the first executable check, run before the shell-command-string detection at lines 62-71.
Source
Thrown at skills/terminal-opener/scripts/open-terminal.js:53
function isAbsolutePath(value) {
return path.isAbsolute(value) || path.win32.isAbsolute(value);
}
function validateTerminalName(value) {
if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(value)) {
throw new Error('Invalid terminal name; use a simple adapter name such as wezterm.');
}
}
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.'
);
}View on GitHub (pinned to 01e15490f0)
Solutions
- Provide a non-empty executable token after -- with no control bytes.
- If the executable comes from a template, sanitize it: strip \0, \r, \n.
- Double-check the token order: executable first, then its arguments.
Example fix
// before parseArgs(['--', '', 'arg']); // empty executable // after parseArgs(['--', '/bin/echo', 'arg']);
Defensive patterns
Strategy: validation
Validate before calling
function safeExecutable(value) {
if (!value || /[\0\r\n]/.test(value)) {
throw new Error('Executable must be non-empty with no control bytes');
}
return value;
} Prevention
- Always pass the executable as a distinct argv token, not interpolated from a template that may inject newlines.
- Reject empty executable tokens early in any wrapper that builds argv.
When it happens
Trigger: options.executable is '' (e.g. '--' immediately followed by another '--' or end of args producing an empty token) or contains \0/\r/\n. validateExecutable is called from parseArgs when an executable is present.
Common situations: Passing an empty executable; a template literal that introduced a newline into the executable name; binary/corrupted argv; accidentally putting a flag where the executable goes.
Related errors
- Invalid terminal name; use a simple adapter name such as wez
- --cwd must not contain a NUL byte.
- Executable must be one argv entry, not an interpolated shell
- Arguments must not contain NUL bytes.
- Invalid ECC repo root: missing install script at ${installAp
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/4388a6a5809a020e.
Report an issue: GitHub.