affaan-m/ECC · error · Error
Invalid terminal name; use a simple adapter name such as wez
Error message
Invalid terminal name; use a simple adapter name such as wezterm.
What it means
validateTerminalName requires the terminal adapter name to match ^[A-Za-z0-9][A-Za-z0-9_.-]*$ — it must start alphanumeric and contain only alphanumerics, dots, dashes, and underscores. This blocks path traversal, shell metacharacters, and option injection in the --terminal value. Only 'wezterm' is actually supported (SUPPORTED_TERMINALS), but the name is syntactically validated first.
Source
Thrown at skills/terminal-opener/scripts/open-terminal.js:42
--standalone Alias for --recover.
--detect Check whether the selected terminal can be launched.
--launch Explicitly open the terminal (the default only prints a plan).
--dry-run Explicitly print the launch plan without opening a terminal.
--json Emit the plan, capability, or launch result as JSON.
--help, -h Show this help.
Always pass the executable and arguments as separate entries after --.
Shell command strings are not accepted.
`;
}
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));View on GitHub (pinned to 01e15490f0)
Solutions
- Use a plain adapter name such as 'wezterm'.
- If ECC_TERMINAL is set wrongly, unset it or set it to 'wezterm'.
- Pass only the adapter name, not a path: --terminal wezterm (no slashes, spaces, or leading dashes).
Example fix
# before ECC_TERMINAL=/usr/bin/wezterm node open-terminal.js -- echo hi # after unset ECC_TERMINAL node open-terminal.js --terminal wezterm -- echo hi
Defensive patterns
Strategy: validation
Validate before calling
function isValidTerminalName(value) {
return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(value);
}
const terminal = process.env.ECC_TERMINAL || 'wezterm';
if (!isValidTerminalName(terminal)) {
throw new Error(`Invalid terminal name: ${JSON.stringify(terminal)}`);
} Prevention
- Pass the adapter name only (e.g. 'wezterm'), never a path.
- Validate ECC_TERMINAL at app startup if it comes from an untrusted source.
- Remember only 'wezterm' is actually supported even if the name passes the regex.
When it happens
Trigger: Passing --terminal (or setting ECC_TERMINAL) to a value that fails the regex: empty string, leading dash/slash/space, or any special character. parseArgs calls validateTerminalName near the end of parsing.
Common situations: ECC_TERMINAL accidentally set to an absolute path like /usr/bin/wezterm; passing --terminal 'wez term' with a space; copying a path from another tool; empty value from an env var.
Related errors
- --cwd must not contain a NUL byte.
- Executable must be a non-empty argv entry without control by
- Executable must be one argv entry, not an interpolated shell
- Arguments must not contain NUL bytes.
- Missing value for ${option}.
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/d98435d929947e3a.
Report an issue: GitHub.