{"record":{"id":"64352ccd4ae4cdfc","repo":"affaan-m/ECC","slug":"nasiko-install-directory-must-be-an-absolute-path","errorCode":null,"errorMessage":"Nasiko install directory must be an absolute path.","messagePattern":"Nasiko install directory must be an absolute path\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/nasiko-release.js","lineNumber":170,"sourceCode":"      });\n      response.on('end', () => resolve(Buffer.concat(chunks)));\n      response.on('error', reject);\n    });\n    request.setTimeout(options.timeoutMs || 15000, () => request.destroy(new Error('Nasiko registry request timed out.')));\n    request.on('error', reject);\n  });\n}\n\nfunction defaultInstallDirectory(normalized, environment = process.env, homeDirectory = os.homedir()) {\n  if (normalized.os === 'windows') {\n    if (!environment.LOCALAPPDATA) throw new Error('LOCALAPPDATA is required on Windows.');\n    return path.join(environment.LOCALAPPDATA, 'nasiko', 'bin');\n  }\n  return path.join(homeDirectory, '.local', 'bin');\n}\n\nfunction validateInstallDirectory(directory) {\n  if (typeof directory !== 'string' || directory.includes('\\0') || !path.isAbsolute(directory)) throw new Error('Nasiko install directory must be an absolute path.');\n  if (/^(?:\\\\\\\\|\\\\\\\\\\?\\\\|\\\\\\\\\\.\\\\)/.test(directory)) throw new Error('Nasiko install directory must be on a local filesystem.');\n  const resolved = path.resolve(directory);\n  if (resolved === path.parse(resolved).root) throw new Error('Nasiko cannot install directly into a filesystem root.');\n  let ancestor = resolved;\n  while (!fs.existsSync(ancestor)) {\n    const parent = path.dirname(ancestor);\n    if (parent === ancestor) throw new Error('Nasiko install directory has no resolvable filesystem ancestor.');\n    ancestor = parent;\n  }\n  const canonical = fs.realpathSync(ancestor);\n  return path.join(canonical, path.relative(ancestor, resolved));\n}\n\nfunction assertPrivateInstallDirectory(directory) {\n  const stats = fs.lstatSync(directory);\n  if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error('Nasiko install directory must be a real directory, not a symlink.');\n  if (process.platform !== 'win32') {\n    if (typeof process.getuid === 'function' && stats.uid !== process.getuid()) throw new Error('Nasiko install directory must be owned by the current user.');","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/nasiko-release.js#L152-L188","documentation":"validateInstallDirectory rejects any install directory that is not a non-empty string, contains a NUL byte, or is not an absolute path (per path.isAbsolute). Relative paths cannot be safely resolved across callers, and NUL bytes are invalid in filesystem paths, so the library fails fast.","triggerScenarios":"Calling installDirectory, parseMutationArguments, candidate, or parseStatusArguments with a --dir/install-dir value that is relative (e.g. 'nasiko/bin'), empty, not a string, or contains a NUL byte.","commonSituations":"Typing a relative path in the CLI; a config file storing the directory without a leading slash/drive letter; shell expansion failing so '$HOME/.local/bin' stays literal; programmatic callers passing undefined.","solutions":["Pass an absolute path (e.g. /home/user/.local/bin or C:\\\\Users\\\\me\\\\nasiko\\\\bin).","Expand environment variables/tilde in the shell before passing: --dir \"$HOME/.local/bin\".","Fix the config file so the stored path is absolute.","For programmatic use, resolve first: path.resolve(relativeDir) before calling."],"exampleFix":"// before\nawait installDirectory({ dir: 'nasiko/bin' });\n// after\nconst path = require('path');\nawait installDirectory({ dir: path.resolve(process.env.HOME, '.local', 'bin') });","handlingStrategy":"validation","validationCode":"function assertAbsoluteInstallDir(d) { if (typeof d !== 'string' || !d || d.includes('\\0') || !path.isAbsolute(d)) throw new Error('Install dir must be a non-empty absolute path without NUL bytes.'); }","typeGuard":"const isAbsoluteInstallDir = (d) => typeof d === 'string' && d.length > 0 && !d.includes('\\0') && path.isAbsolute(d);","tryCatchPattern":"try { await installDirectory({ dir }); } catch (err) { if (err.message.includes('must be an absolute path')) throw new Error('Fix --dir: pass an absolute path, got: ' + dir); throw err; }","preventionTips":["Expand $HOME/tilde in shell before passing directory flags","Store absolute paths in config files","Resolve programmatically with path.resolve() before calling","Validate CLI input in your wrapper before delegating"],"tags":["path","validation","cli"],"backgroundTag":"invalid-argument-value","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"}