affaan-m/ECC · error
Nasiko install directory must be on a local filesystem.
Error message
Nasiko install directory must be on a local filesystem.
What it means
The second gate in validateInstallDirectory rejects Windows UNC paths (\\server\share...) and Win32 device-namespace prefixes (\\?\, \\.\) via a leading-backslash pattern check. The installer only writes to local filesystems so that atomic-rename semantics, permissions, and symlink behavior are predictable. Network shares are explicitly out of scope.
Source
Thrown at scripts/lib/nasiko-release.js:143
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.');
if ((stats.mode & 0o022) !== 0) throw new Error('Nasiko install directory must not be group- or world-writable.');View on GitHub (pinned to 06c5e118c4)
Solutions
- Install to a local directory such as the LOCALAPPDATA default or C:\tools\nasiko\bin
- Map the share to a drive letter (net use N: \\fileserver\builds) and pass N:\nasiko\bin if a share must be involved - or better, install locally and copy
- Remove \\?\ / \\.\ prefixes from configured paths
Example fix
// before: UNC share passed directly
installNasiko({ directory: String.raw`\\fileserver\builds\nasiko\bin` }); // throws
// after: local path
installNasiko({ directory: path.join(env.LOCALAPPDATA, 'nasiko', 'bin') }); Defensive patterns
Strategy: validation
Validate before calling
function isLocalAbsolutePath(dir) {
// Rejects UNC (\\server\share) and device (\\?\, \\.\) prefixes.
return path.isAbsolute(dir) && !dir.startsWith(String.raw`\\`);
}
if (!isLocalAbsolutePath(configuredDir)) {
throw new Error('Install directory must be a local absolute path, not a UNC/device path');
} Type guard
const isLocalAbsoluteWindowsPath = (p: string): boolean => /^[A-Za-z]:[\\/]/.test(p) && !p.startsWith(String.raw`\\`);
Try / catch
try {
await installNasiko({ directory: configuredDir });
} catch (error) {
if (/must be on a local filesystem/.test(String(error.message))) {
// Map the share to a drive letter or choose a local directory, then retry.
}
throw error;
} Prevention
- Default to %LOCALAPPDATA%\nasiko\bin or another local path in configs
- Strip \\?\ long-path prefixes from user-supplied directories
- Reject UNC inputs in config validation so the installer never sees them
When it happens
Trigger: Passing directory: '\\\\fileserver\\builds\\nasiko' (UNC), or a long-path/device form beginning with '\\\\?\\' or '\\\\.\\'. These start with backslashes and match the reject pattern even though path.isAbsolute() considers them absolute on Windows.
Common situations: Corporate CI configs pointing at SMB/NAS shares; users putting tools on mapped-by-UNC home directories; developers attempting to sidestep MAX_PATH with the \\?\ prefix.
Related errors
- LOCALAPPDATA is required on Windows.
- Nasiko install directory must be an absolute path.
- Nasiko cannot install directly into a filesystem root.
- Agents directory not found: ${dirPath}
- Expected a directory: ${dirPath}
AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18).
Data as JSON: /api/errors/5ea1b260f529ded9.
Report an issue: GitHub.