{"record":{"id":"8da6c06e740c4951","repo":"affaan-m/ECC","slug":"cwd-must-be-an-absolute-path","errorCode":null,"errorMessage":"--cwd must be an absolute path.","messagePattern":"--cwd must be an absolute path\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/terminal-opener/scripts/open-terminal.js","lineNumber":48,"sourceCode":"\nAlways pass the executable and arguments as separate entries after --.\nShell command strings are not accepted.\n`;\n}\n\nfunction isAbsolutePath(value) {\n  return path.isAbsolute(value) || path.win32.isAbsolute(value);\n}\n\nfunction validateTerminalName(value) {\n  if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(value)) {\n    throw new Error('Invalid terminal name; use a simple adapter name such as wezterm.');\n  }\n}\n\nfunction validateCwd(value) {\n  if (value.includes('\\0')) throw new Error('--cwd must not contain a NUL byte.');\n  if (!isAbsolutePath(value)) throw new Error('--cwd must be an absolute path.');\n}\n\nfunction validateExecutable(value) {\n  if (!value || /[\\0\\r\\n]/.test(value)) {\n    throw new Error('Executable must be a non-empty argv entry without control bytes.');\n  }\n\n  const whitespaceIndex = value.search(/\\s/);\n  const separatorIndexes = [value.indexOf('/'), value.indexOf('\\\\')].filter(index => index >= 0);\n  const firstSeparatorIndex = separatorIndexes.length > 0 ? Math.min(...separatorIndexes) : -1;\n  const resemblesExecutablePath = isAbsolutePath(value)\n    || (firstSeparatorIndex >= 0 && (whitespaceIndex < 0 || firstSeparatorIndex < whitespaceIndex));\n\n  if (whitespaceIndex >= 0 && !resemblesExecutablePath) {\n    throw new Error(\n      'Executable must be one argv entry, not an interpolated shell command string.'\n    );\n  }","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/terminal-opener/scripts/open-terminal.js#L30-L66","documentation":"validateCwd requires the --cwd value to be an absolute path on the current platform; it checks both POSIX (path.isAbsolute) and Windows (path.win32.isAbsolute) forms. Relative paths are ambiguous once the terminal process spawns in an unrelated working directory, so the script rejects them. Pass an absolute directory to launch the terminal in.","triggerScenarios":"Running `open-terminal.js --cwd .`, `--cwd ../project`, or `--cwd myfolder` instead of a resolved absolute path.","commonSituations":"Users habitually pass relative paths from the shell; scripts that don't call path.resolve before invoking; shell aliases that expand to relative directories.","solutions":["Resolve the directory first: `node open-terminal.js --cwd \"$(pwd)/project\"` or in JS `path.resolve('myfolder')`.","Use an absolute path with drive letter on Windows, e.g. `--cwd C:\\\\Users\\\\me\\\\project`.","Have calling scripts always pass `path.resolve(cwd)` output."],"exampleFix":"// before\nnode open-terminal.js --cwd ../myproject\n// after\nnode open-terminal.js --cwd \"$(cd ../myproject && pwd)\"","handlingStrategy":"validation","validationCode":"const path = require('path');\nconst isAbs = (v) => path.isAbsolute(v) || path.win32.isAbsolute(v);\nif (!isAbs(cwd)) throw new Error('cwd must be absolute: ' + path.resolve(cwd));","typeGuard":"function isAbsoluteCrossPlatform(v) {\n  return typeof v === 'string' && (require('path').isAbsolute(v) || require('path').win32.isAbsolute(v));\n}","tryCatchPattern":"try {\n  parseArgs(process.argv);\n} catch (e) {\n  if (/must be an absolute path/.test(e.message)) {\n    console.error('Resolve with path.resolve() before passing --cwd');\n  } else throw e;\n}","preventionTips":["Always path.resolve() directories before passing to CLI tools.","Use $(pwd)-style expansion in shell wrappers.","Never rely on the child process inheriting your CWD.","Add absolute-path assertions in scripts that invoke the tool."],"tags":["cli","validation","path"],"backgroundTag":"invalid-cli-argument","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}