affaan-m/ECC · error
An unqualified or incompatible Nasiko executable or receipt…
Error message
An unqualified or incompatible Nasiko executable or receipt already exists at the destination.
What it means
Thrown by installNasiko when the destination path already contains a Nasiko executable/receipt that is either not the qualified pinned build or whose recorded version differs from the requested version. The installer refuses to overwrite an existing file it cannot verify, so it aborts instead of clobbering. An exact version match that is qualified is silently reused.
Solutions
- Run the Nasiko uninstall flow (with --yes) for the destination to remove the unqualified or mismatched executable, then reinstall.
- Install the version already present at the destination (pass the existing version) so the installer takes the reuse path.
- Manually remove the destination file and its metadata receipt (metadataPathFor(destination)) and retry the install.
- Verify the binary was not modified after install (chmod/rename/truncate breaks qualification) and restore it from a clean source.
Example fix
// before
await installNasiko({ version: 'v0.2.0' }); // throws: v0.1.0 already at destination
// after
await uninstallNasiko({ version: 'v0.1.0', yes: true });
await installNasiko({ version: 'v0.2.0' }); Defensive patterns
Strategy: validation
Validate before calling
import { inspectInstalledNasiko } from './nasiko-release.js';
const status = inspectInstalledNasiko(destination);
if (status.installed && (!status.qualified || status.version !== desiredVersion)) {
await uninstallNasiko({ version: status.version, yes: true });
} Type guard
function isCleanDestination(destination, version) {
const s = inspectInstalledNasiko(destination);
return !s.installed || (s.qualified && s.version === version);
} Try / catch
try {
await installNasiko({ version });
} catch (e) {
if (e.message.includes('already exists at the destination')) {
await uninstallNasiko({ yes: true });
await installNasiko({ version });
} else throw e;
} Prevention
- Always uninstall the old version before installing a new one
- Never hand-edit or patch the installed binary after install
- Use the reuse path when the desired version is already installed
- Check inspectInstalledNasiko before calling install
When it happens
Trigger: Calling installNasiko when inspectInstalledNasiko(destination).installed is true and either existing.qualified is false (file present but digest/qualification check failed) or existing.version !== version (different version already installed).
Common situations: A stale Nasiko binary left over from a previous install or manual download; upgrading Nasiko in place without uninstalling the old version first; a corrupted or user-modified binary that no longer passes qualification; reinstalling after a partial/unqualified bootstrap.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- A normalized install request is required
- Circular install dependency detected at
- Invalid install-state
- destination is not writable by the current user: . Fix the…
- Legacy language arguments cannot be combined with…
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/65a87fb7f17f8af0.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/nasiko-release.js:398
const version = options.version || 'v0.1.0';
const base = getQualifiedRelease(version, dependencies.platform || process.platform, dependencies.arch || process.arch);
const release = dependencies.releaseOverride ? { ...base, ...dependencies.releaseOverride } : base;
const installDirectory = validateInstallDirectory(options.installDir || defaultInstallDirectory(release, dependencies.environment || process.env, dependencies.homeDirectory || os.homedir()));
const destination = path.join(installDirectory, release.binaryName);
const plan = { dryRun: Boolean(options.dryRun), version, platform: release.os, architecture: release.arch, manifestDigest: release.manifestDigest, binaryDigest: release.binaryDigest, registryOrigin: REGISTRY_ORIGIN, destination, license: release.license, sourceUrl: release.sourceUrl };
if (options.dryRun) return plan;
if (!options.yes) throw new Error('Nasiko installation requires explicit --yes consent.');
fs.mkdirSync(installDirectory, { recursive: true, mode: 0o755 });
assertPrivateInstallDirectory(installDirectory);
const releaseLock = acquireLifecycleLock(installDirectory);
const metadataPath = metadataPathFor(destination);
let destinationOwned = false;
let metadataOwned = false;
try {
const existing = inspectInstalledNasiko(destination);
if (existing.installed) {
if (existing.qualified && existing.version === version) return { ...plan, dryRun: false, installed: true, reused: true };
throw new Error('An unqualified or incompatible Nasiko executable or receipt already exists at the destination.');
}
const retrieve = dependencies.fetchBytes || fetchBytes;
const manifestBytes = await retrieve(`${REGISTRY_ORIGIN}/v2/${REPOSITORY}/manifests/${release.manifestDigest}`, { accept: 'application/vnd.oci.image.manifest.v1+json', maxBytes: MAX_MANIFEST_BYTES });
assertDigest(manifestBytes, release.manifestDigest, 'Nasiko manifest');
const layer = validateManifest(manifestBytes);
const archiveBytes = await retrieve(`${REGISTRY_ORIGIN}/v2/${REPOSITORY}/blobs/${layer.digest}`, { maxBytes: MAX_ARCHIVE_BYTES });
if (archiveBytes.length !== layer.size) throw new Error('Nasiko archive size mismatch.');
assertDigest(archiveBytes, layer.digest, 'Nasiko archive');
const binary = (dependencies.extractBinary || extractQualifiedTarGzip)(archiveBytes, release.binaryName);
assertDigest(binary, release.binaryDigest, 'Nasiko binary');
if (dependencies.beforePublish) dependencies.beforePublish(destination);
const descriptor = fs.openSync(destination, 'wx', 0o700);
destinationOwned = true;
try {
fs.writeFileSync(descriptor, binary);
fs.fsyncSync(descriptor);
if (fs.fstatSync(descriptor).size !== binary.length) throw new Error('Published Nasiko binary size mismatch.');
} finally { fs.closeSync(descriptor); }View on GitHub (pinned to 8321021c54)