affaan-m/ECC · error
Nasiko install directory must be owned by the current user.
Error message
Nasiko install directory must be owned by the current user.
What it means
On non-Windows platforms, the library checks that the install directory's owning UID matches process.getuid(). If the directory is owned by another user, it throws this error to prevent installing into a location another account controls (a privilege-escalation vector).
Solutions
- Run the install as the user who owns the directory (matching UID).
- Chown the directory to the current user: `sudo chown $(id -u):$(id -g) <dir>`.
- Choose a different installDir owned by the current user (e.g. ~/.local/bin).
- Avoid running the installer with sudo into user-owned paths; install per-user instead.
Example fix
// before (directory owned by root) sudo mkdir -p /opt/nasiko/bin && nasiko install // after sudo chown -R "$(id -u):$(id -g)" /opt/nasiko/bin nasiko install --install-dir /opt/nasiko/bin --yes
Defensive patterns
Strategy: validation
Validate before calling
const stats = fs.statSync(dir)
if (typeof process.getuid === 'function' && stats.uid !== process.getuid()) {
throw new Error(`installDir owned by uid ${stats.uid}, not ${process.getuid()}`)
} Try / catch
try {
await installNasiko({ installDir: dir, yes: true })
} catch (e) {
if (e.message.includes('owned by the current user')) {
console.error(`Run: sudo chown $(id -u):$(id -g) ${dir} — or pick a user-owned installDir`)
}
throw e
} Prevention
- Install per-user (~/.local/bin) rather than into system paths.
- Never run installs with sudo into user-owned directories.
- Check ownership with `ls -ld` before configuring a custom installDir.
- In containers, ensure HOME and the install dir are created by the same user.
When it happens
Trigger: installNasiko or uninstallNasiko where the install directory's lstat uid differs from the current user — e.g. installDir pointing at /usr/local/bin or another user's home directory while running as an unprivileged user.
Common situations: Trying to install system-wide (/usr/local/bin) without sudo or vice versa (running with sudo but dir owned by user); shared machines where a teammate created the directory; containers where HOME/user was remapped and the directory retains a different UID.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- Nasiko install directory must not be group- or…
- artifact must be a resident regular file
- artifact path escapes output directory
- artifact path must be canonical and absolute
- artifact permits provider execution
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/8f0272dc8a9567af.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/nasiko-release.js:188
if (typeof directory !== 'string' || directory.includes('\0') || !path.isAbsolute(directory)) throw new Error('Nasiko install directory must be an absolute path.');
if (/^(?:\\\\|\\\\\?\\|\\\\\.\\)/.test(directory)) throw new Error('Nasiko install directory must be on a local filesystem.');
const resolved = path.resolve(directory);
if (resolved === path.parse(resolved).root) throw new Error('Nasiko cannot install directly into a filesystem root.');
let ancestor = resolved;
while (!fs.existsSync(ancestor)) {
const parent = path.dirname(ancestor);
if (parent === ancestor) throw new Error('Nasiko install directory has no resolvable filesystem ancestor.');
ancestor = parent;
}
const canonical = fs.realpathSync(ancestor);
return path.join(canonical, path.relative(ancestor, resolved));
}
function assertPrivateInstallDirectory(directory) {
const stats = fs.lstatSync(directory);
if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error('Nasiko install directory must be a real directory, not a symlink.');
if (process.platform !== 'win32') {
if (typeof process.getuid === 'function' && stats.uid !== process.getuid()) throw new Error('Nasiko install directory must be owned by the current user.');
if ((stats.mode & 0o022) !== 0) throw new Error('Nasiko install directory must not be group- or world-writable.');
}
}
function metadataPathFor(executable) { return path.join(path.dirname(executable), METADATA_FILENAME); }
function readBoundedRegularFile(filePath, maximumBytes) {
const noFollow = fs.constants.O_NOFOLLOW;
const descriptor = fs.openSync(filePath, fs.constants.O_RDONLY | (noFollow || 0));
try {
const stats = fs.fstatSync(descriptor);
if (!stats.isFile() || stats.size <= 0 || stats.size > maximumBytes) return null;
if (!noFollow) {
const pathStats = fs.lstatSync(filePath);
if (pathStats.isSymbolicLink()
|| pathStats.dev !== stats.dev
|| pathStats.ino !== stats.ino
|| pathStats.birthtimeMs !== stats.birthtimeMs) {View on GitHub (pinned to 8321021c54)