{"record":{"id":"c8537e5f10d4bf02","repo":"affaan-m/ECC","slug":"nasiko-cannot-install-directly-into-a-filesystem-r","errorCode":null,"errorMessage":"Nasiko cannot install directly into a filesystem root.","messagePattern":"Nasiko cannot install directly into a filesystem root\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/nasiko-release.js","lineNumber":173,"sourceCode":"    });\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.');\n    if ((stats.mode & 0o022) !== 0) throw new Error('Nasiko install directory must not be group- or world-writable.');\n  }\n}","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/nasiko-release.js#L155-L191","documentation":"validateInstallDirectory resolves the requested path and refuses a path equal to the filesystem root (e.g. / on POSIX, C:\\ on Windows). Installing directly into a root would scatter binaries and directories at the top level of a volume, so it is blocked. A non-root error ('no resolvable filesystem ancestor') exists for the opposite case of a path whose ancestors are all unresolvable.","triggerScenarios":"Calling installDirectory, parseMutationArguments, candidate, or parseStatusArguments with --dir / or --dir C:\\\\ (or any drive root), so path.resolve(dir) === path.parse(resolved).root.","commonSituations":"CLI users typing '--dir /' as shorthand for 'system-wide'; scripts parameterized with an empty suffix (prefix + '' collapses to root); config defaulting to a bare drive letter on Windows.","solutions":["Choose a real subdirectory, e.g. /usr/local/bin or C:\\\\Users\\\\me\\\\nasiko\\\\bin.","Fix the templating/script bug where the directory component was dropped and only the root remained.","Add a guard in your wrapper that rejects root paths before delegating to the library.","If a config file specifies the root, edit it to a concrete absolute subpath."],"exampleFix":"// before\nconst dir = process.env.NASIKO_PREFIX || '/';\nawait installDirectory({ dir });\n// after\nconst dir = process.env.NASIKO_PREFIX || '/usr/local/bin';\nif (path.resolve(dir) === path.parse(path.resolve(dir)).root) throw new Error('Refusing filesystem root install dir.');\nawait installDirectory({ dir });","handlingStrategy":"validation","validationCode":"const r = path.resolve(dir); if (r === path.parse(r).root) throw new Error('Install dir must be a subdirectory, not a filesystem root.');","typeGuard":"const isNonRootDir = (d) => { const r = path.resolve(d); return r !== path.parse(r).root; };","tryCatchPattern":"try { await installDirectory({ dir }); } catch (err) { if (err.message.includes('filesystem root')) throw new Error('Refusing root install; pass a concrete subdirectory.'); throw err; }","preventionTips":["Never default install paths to '/' or a bare drive letter","Check template expansions so an empty suffix cannot collapse the path to root","Validate that the chosen dir resolves to more than just a root component","Prefer standard locations like ~/.local/bin or %LOCALAPPDATA%\\\\nasiko\\\\bin"],"tags":["path","validation","filesystem"],"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"}