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

  1. Split the command: pass only the program in --executable and the remaining words as arguments after `--`.
  2. If you truly mean a path-like value, use an absolute path containing `/` before any whitespace (e.g. `/usr/local/bin/my exe` quoted).
  3. 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

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


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)