affaan-m/ECC · error · Error

Nasiko installation requires a pinned version such as…

Error message

Nasiko installation requires a pinned version such as v0.1.0; latest is not allowed.

What it means

getQualifiedRelease requires an exact semver version string in the form vX.Y.Z because Nasiko installs are pinned to cryptographically qualified releases. 'latest', loose versions ('0.1.0' without 'v'), ranges, or empty input throw, ensuring digest pinning is always explicit.

Solutions

  1. Use an exact pinned tag like v0.1.0
  2. Strip/add the 'v' prefix to match ^v\d+\.\d+\.\d+$
  3. Check QUALIFIED_RELEASES in scripts/lib/nasiko-release.js for versions that exist
  4. Resolve 'latest' manually by looking up the newest release tag first

Example fix

// before
getQualifiedRelease('latest');
// after
getQualifiedRelease('v0.1.0');
Defensive patterns

Strategy: validation

Validate before calling

const VERSION_RE = /^v\d+\.\d+\.\d+$/;
if (!VERSION_RE.test(String(version ?? ''))) {
  throw new Error(`version must match vX.Y.Z, got: ${version}`);
}

Type guard

function isPinnedVersion(v) {
  return typeof v === 'string' && /^v\d+\.\d+\.\d+$/.test(v);
}

Try / catch

try {
  const rel = getQualifiedRelease(version);
} catch (e) {
  if (e.message.includes('pinned version')) {
    console.error('Resolve latest to a concrete tag, e.g. v0.1.0, and retry.');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing 'latest', 'v0.1', '0.1.0', 'v0.1.0-beta', or an unset version into getQualifiedRelease (directly or via the Nasiko install command/config).

Common situations: Using 'latest' out of habit from npm; reading a version from package.json that lacks the 'v' prefix; config/env interpolation producing an empty version; attempting a prerelease build.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/5e9fa5caa305c585. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/nasiko-release.js:42

    'linux/arm64': Object.freeze({ manifestDigest: 'sha256:655021a129c7df4621a80d16ea4eab38018530bfe9a20da646641d9f4ac5c249', binaryDigest: 'sha256:85f9fa5cfbed6c276fce6df2d71e9d0c66d7d8e8d46a40297464833d38db7a7e' }),
    'darwin/amd64': Object.freeze({ manifestDigest: 'sha256:b4188482621efd7da5a2ab630f653665ab5f80b9aceae448b6bb5fc93e003f06', binaryDigest: 'sha256:ed6232e0bb96a2dcfd86d3c25f86021091600d52f09250403a54528bfe8100a3' }),
    'darwin/arm64': Object.freeze({ manifestDigest: 'sha256:ce7e54fa19f989a5d125c4409b3587ca9503bb5a07bc5ff223c60e0fbad437f0', binaryDigest: 'sha256:3c60f862b04eea1b9a633593b39f1a443d9ca2123cf3edfd150d313e95f3894b' }),
    'windows/amd64': Object.freeze({ manifestDigest: 'sha256:0760fe1fc98e8fedb66796aaf891a1de9268af1338c5e88b949656fda5d9f045', binaryDigest: 'sha256:0f57672d24fc3c70e4cbbf22864e65b35b9978ddaae3793803841536e682929b' }),
  }),
});

function normalizePlatform(platform = process.platform, architecture = process.arch) {
  const osName = platform === 'win32' ? 'windows' : platform;
  if (!['linux', 'darwin', 'windows'].includes(osName)) throw new Error(`Unsupported platform: ${platform}`);
  const arch = architecture === 'x64' ? 'amd64' : architecture;
  if (!['amd64', 'arm64'].includes(arch)) throw new Error(`Unsupported architecture: ${architecture}`);
  if (osName === 'windows' && arch !== 'amd64') throw new Error(`Unsupported architecture for Windows: ${architecture}`);
  return { os: osName, arch, binaryName: osName === 'windows' ? 'nasiko.exe' : 'nasiko' };
}

function getQualifiedRelease(version, platform = process.platform, architecture = process.arch) {
  if (!/^v\d+\.\d+\.\d+$/.test(String(version || ''))) {
    throw new Error('Nasiko installation requires a pinned version such as v0.1.0; latest is not allowed.');
  }
  const normalized = normalizePlatform(platform, architecture);
  const qualification = QUALIFIED_RELEASES[version]?.[`${normalized.os}/${normalized.arch}`];
  if (!qualification) throw new Error(`Nasiko ${version} is not qualified for ${normalized.os}/${normalized.arch}.`);
  return { version, ...normalized, ...qualification, license: LICENSE, sourceUrl: SOURCE_URL };
}

function digestBytes(bytes) {
  return `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`;
}

function assertDigest(bytes, expectedDigest, label) {
  if (!SHA256_PATTERN.test(expectedDigest)) throw new Error(`${label} has an invalid expected digest.`);
  const actual = digestBytes(bytes);
  if (actual !== expectedDigest) throw new Error(`${label} digest mismatch: expected ${expectedDigest}, got ${actual}.`);
}

function validateManifest(bytes) {

View on GitHub (pinned to 8321021c54)