affaan-m/ECC · error
Nasiko install directory must not be group- or…
Error message
Nasiko install directory must not be group- or world-writable.
What it means
On non-Windows platforms the library requires the install directory's permission bits to exclude group-write and other-write (mode & 0o022 === 0). If the directory is group- or world-writable, it throws this error, because any local user could replace the installed binary between verification and execution.
Solutions
- Tighten permissions: `chmod go-w <dir>` (or `chmod 755 <dir>`), then retry.
- Check and fix your umask (e.g. `umask 022`) before creating install directories.
- Create a fresh directory with restrictive defaults: `mkdir -m 755 <dir>`.
- Verify with `stat -c '%a' <dir>` that group/other write bits are clear.
Example fix
// before
ls -ld ~/.local/bin # drwxrwxrwx
installNasiko({ yes: true })
// after
chmod 755 ~/.local/bin
installNasiko({ yes: true }) Defensive patterns
Strategy: validation
Validate before calling
const mode = fs.statSync(dir).mode & 0o777
if ((mode & 0o022) !== 0) throw new Error(`installDir too permissive: ${mode.toString(8)}`) Try / catch
try {
await installNasiko({ installDir: dir, yes: true })
} catch (e) {
if (e.message.includes('group- or world-writable')) {
fs.chmodSync(dir, 0o755)
return installNasiko({ installDir: dir, yes: true })
}
throw e
} Prevention
- Create install directories with mode 755 explicitly (mkdir -m 755).
- Set umask 022 in shell profiles and CI.
- Avoid directories on FAT/exFAT mounts that force 0777.
- Audit permissions with `stat -c '%a'` before custom install paths.
When it happens
Trigger: installNasiko or uninstallNasiko where lstat on the install directory shows mode bits 0o022 set — e.g. a directory created with mode 0777 or 0775, or a umask that left group/other write enabled.
Common situations: Creating the directory with `mkdir -m 777`; shared team servers where bin directories are group-writable; copying a directory from a FAT/exFAT mount that defaults to 0777; overly permissive umask (0000) in CI.
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 be owned by the current user.
- Nasiko install directory must be a real directory, not a…
- artifact must be a resident regular file
- artifact path escapes output directory
- artifact path must be canonical and absolute
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/4a6d130c71bbb40d.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/nasiko-release.js:189
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) {
const error = new Error('Nasiko managed files must not be symbolic links or reparse points.');View on GitHub (pinned to 8321021c54)