{"record":{"id":"d692388bc59aa6b8","repo":"affaan-m/ECC","slug":"nasiko-manifest-is-not-valid-json","errorCode":null,"errorMessage":"Nasiko manifest is not valid JSON.","messagePattern":"Nasiko manifest is not valid JSON\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/nasiko-release.js","lineNumber":62,"sourceCode":"  const normalized = normalizePlatform(platform, architecture);\n  const qualification = QUALIFIED_RELEASES[version]?.[`${normalized.os}/${normalized.arch}`];\n  if (!qualification) throw new Error(`Nasiko ${version} is not qualified for ${normalized.os}/${normalized.arch}.`);\n  return { version, ...normalized, ...qualification, license: LICENSE, sourceUrl: SOURCE_URL };\n}\n\nfunction digestBytes(bytes) {\n  return `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`;\n}\n\nfunction assertDigest(bytes, expectedDigest, label) {\n  if (!SHA256_PATTERN.test(expectedDigest)) throw new Error(`${label} has an invalid expected digest.`);\n  const actual = digestBytes(bytes);\n  if (actual !== expectedDigest) throw new Error(`${label} digest mismatch: expected ${expectedDigest}, got ${actual}.`);\n}\n\nfunction validateManifest(bytes) {\n  let manifest;\n  try { manifest = JSON.parse(bytes.toString('utf8')); } catch (_error) { throw new Error('Nasiko manifest is not valid JSON.'); }\n  if (manifest.schemaVersion !== 2 || !Array.isArray(manifest.layers) || manifest.layers.length !== 1) {\n    throw new Error('Nasiko manifest must contain exactly one OCI layer.');\n  }\n  const layer = manifest.layers[0];\n  if (layer.mediaType !== 'application/gzip' || !SHA256_PATTERN.test(layer.digest)) {\n    throw new Error('Nasiko manifest layer is not a qualified gzip artifact.');\n  }\n  if (!Number.isSafeInteger(layer.size) || layer.size <= 0 || layer.size > MAX_ARCHIVE_BYTES) {\n    throw new Error('Nasiko manifest layer size is outside the allowed range.');\n  }\n  return { digest: layer.digest, size: layer.size };\n}\n\nfunction readTarString(block, offset, length) {\n  return block.subarray(offset, offset + length).toString('utf8').replace(/\\0.*$/, '');\n}\n\nfunction extractQualifiedTarGzip(archiveBytes, expectedName) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/lib/nasiko-release.js#L44-L80","documentation":"validateManifest in scripts/lib/nasiko-release.js runs JSON.parse over the manifest bytes downloaded from the registry after the manifest digest already matched. If parsing throws, the body is not valid JSON, so it can never be a valid OCI manifest. The digest having matched means the corruption happened on the producer side or in this script's expectations, not in transit.","triggerScenarios":"The registry returns HTTP 200 with a non-JSON body whose sha256 still matches the pinned manifest digest: an upstream packaging change, a different artifact stored under the same digest in a mirror, or an incorrectly pinned digest in QUALIFIED_RELEASES.","commonSituations":"Upstream changed the manifest format (for example switching to an OCI artifact index) without a version bump in this script's pinned digests; private registry mirrors serving substituted content; maintainers re-generating artifacts with new formatting for the same tag.","solutions":["Inspect the actual manifest: `curl -sS https://registry.nasiko.dev/v2/nasiko/nasiko/manifests/v0.1.0 | head -c 400` to see what was returned","Update the ECC checkout so the pinned manifestDigest matches the currently served artifact","If you control releases, re-qualify the release and update both digests in QUALIFIED_RELEASES","Report persistent mismatches upstream rather than skipping validation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await installNasiko({ version: 'v0.1.0' });\n} catch (error) {\n  if (/manifest is not valid JSON/.test(String(error.message))) {\n    // Digest already matched, so the registry itself served non-JSON under the\n    // pinned digest. Inspect the served manifest manually and update the pinned\n    // digests/checkout; do not retry blindly.\n  }\n  throw error;\n}","preventionTips":["Keep the installer (and its pinned digests) updated when upstream re-publishes artifacts","Fetch and eyeball the manifest with curl once when wiring up new mirrors","Treat format changes on pinned digests as release-process defects to fix upstream"],"tags":["json","manifest","oci"],"backgroundTag":"invalid-json","analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}