affaan-m/ECC · error
Nasiko install directory must be an absolute path.
Error message
Nasiko install directory must be an absolute path.
What it means
validateInstallDirectory in scripts/lib/nasiko-release.js is the first gate on caller-supplied install paths: the value must be a string, contain no NUL bytes, and be absolute (path.isAbsolute). Relative or malformed input is rejected before any filesystem work happens. The subsequent checks (local filesystem, not a root, resolvable ancestor) run only after this passes.
Source
Thrown at scripts/lib/nasiko-release.js:142
});
response.on('end', () => resolve(Buffer.concat(chunks)));
response.on('error', reject);
});
request.setTimeout(options.timeoutMs || 15000, () => request.destroy(new Error('Nasiko registry request timed out.')));
request.on('error', reject);
});
}
function defaultInstallDirectory(normalized, environment = process.env, homeDirectory = os.homedir()) {
if (normalized.os === 'windows') {
if (!environment.LOCALAPPDATA) throw new Error('LOCALAPPDATA is required on Windows.');
return path.join(environment.LOCALAPPDATA, 'nasiko', 'bin');
}
return path.join(homeDirectory, '.local', 'bin');
}
function validateInstallDirectory(directory) {
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.');View on GitHub (pinned to 06c5e118c4)
Solutions
- Expand and resolve before calling: `path.resolve(rawDir.replace(/^~(?=[/\\]|$)/, os.homedir()))`
- Use path.join(os.homedir(), '.local', 'bin') or another constructed absolute path
- Validate config inputs with a schema that requires an absolute path string
Example fix
// before: tilde is relative to Node, not the shell
installNasiko({ directory: '~/.local/bin' }); // throws
// after
installNasiko({ directory: path.join(os.homedir(), '.local', 'bin') }); Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const os = require('os');
const path = require('path');
function toInstallDir(raw) {
const expanded = raw.replace(/^~(?=[/\\]|$)/, os.homedir());
const dir = path.resolve(expanded);
if (!path.isAbsolute(dir)) throw new Error(`Install directory must be absolute: ${raw}`);
return dir;
} Type guard
const isAbsoluteLocalPath = (p: unknown): p is string =>
typeof p === 'string' && !p.includes('\0') && path.isAbsolute(p); Try / catch
try {
await installNasiko({ directory: configuredDir });
} catch (error) {
if (/must be an absolute path/.test(String(error.message))) {
// Expand '~' and resolve relatives before retrying; schema-validate config.
}
throw error;
} Prevention
- Never pass shell-style '~' paths into Node APIs; expand with os.homedir() first
- Schema-validate user config: directory must be a non-empty absolute path string
- Centralize path normalization in one helper used by all installer callers
When it happens
Trigger: Passing directory: '~/.local/bin' (tilde is not expanded by Node, so it is relative), './bin', 'nasiko/bin', undefined, a non-string value, or a string containing a NUL character.
Common situations: Shell-style paths copied into JS configs where '~' is never expanded; config files with relative paths that worked with other tools (which expand or chdir first); templating bugs injecting empty strings; values sourced from JSON that arrive as null.
Related errors
- Nasiko cannot install directly into a filesystem root.
- Install module ${moduleId} has invalid targets; expected an
- Install module ${moduleId} has unsupported targets: ${unsupp
- Unknown install module: ${unknownModuleIds[0]}
- Unknown install modules: ${unknownModuleIds.join(', ')}
AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18).
Data as JSON: /api/errors/64352ccd4ae4cdfc.
Report an issue: GitHub.