affaan-m/ECC · error · Error

Nasiko archive is invalid or exceeds the decompressed size…

Error message

Nasiko archive is invalid or exceeds the decompressed size limit.

What it means

extractQualifiedTarGzip gunzips the archive with an explicit maxOutputLength of MAX_BINARY_BYTES + 2048 and wraps any gunzip failure in this single error. It is thrown when the input is not valid gzip data or when decompressing would exceed the decompressed-size limit — a guard against corrupt inputs and decompression bombs.

Solutions

  1. Check the first two bytes of the artifact are 0x1f 0x8b (gzip magic); if not, you are extracting the wrong blob or an error page.
  2. Re-download the artifact — truncation mid-gzip stream is the most frequent cause.
  3. Verify the artifact's actual decompressed size fits under MAX_BINARY_BYTES + 2048; if it legitimately grew, the library limit must be respected — republish a smaller artifact.
  4. Confirm the layer digest verified before extraction so you are not debugging a corrupt blob.

Example fix

// before
extractQualifiedTarGzip(downloadedBytes, 'bin'); // gunzip fails
// after
const head = downloadedBytes.subarray(0, 2);
if (!(head[0] === 0x1f && head[1] === 0x8b)) {
  throw new Error(`not gzip: starts with ${head.toString('hex')} — check download/URL`);
}
extractQualifiedTarGzip(downloadedBytes, 'bin');
Defensive patterns

Strategy: try-catch

Validate before calling

const head = archiveBytes.subarray(0, 2);
if (!(head[0] === 0x1f && head[1] === 0x8b)) throw new Error('not gzip data');
const tar = zlib.gunzipSync(archiveBytes, { maxOutputLength: MAX_BINARY_BYTES + 2048 });

Type guard

const isGzip = (b) => b?.length >= 2 && b[0] === 0x1f && b[1] === 0x8b;

Try / catch

try { installNasiko(opts); } catch (e) { if (e.message.includes('decompressed size limit') || e.message.includes('archive is invalid')) { console.error('bad gzip or bomb; refetch verified artifact'); } throw e; }

Prevention

When it happens

Trigger: installNasiko (via tests/extraction path) passes bytes to extractQualifiedTarGzip that are not gzip-compressed, are truncated mid-stream, or whose decompressed size exceeds MAX_BINARY_BYTES + 2048, causing zlib.gunzipSync to throw.

Common situations: Downloaded artifact is actually plain tar or a text error page (no gzip magic), transfer truncated the file, or a malicious/oversized layer attempts a decompression bomb that the limit correctly rejects.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

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

function readTarString(block, offset, length) {
  return block.subarray(offset, offset + length).toString('utf8').replace(/\0.*$/, '');
}

function readTarOctal(block, offset, length) {
  const field = block.subarray(offset, offset + length).toString('ascii');
  const match = /^ *([0-7]+)[ \0]*$/.exec(field);
  if (!match) throw new Error('Unsafe Nasiko archive: invalid tar size field.');
  const size = Number.parseInt(match[1], 8);
  if (!Number.isSafeInteger(size) || size < 0) {
    throw new Error('Unsafe Nasiko archive: invalid tar size field.');
  }
  return size;
}

function extractQualifiedTarGzip(archiveBytes, expectedName) {
  let tar;
  try { tar = zlib.gunzipSync(archiveBytes, { maxOutputLength: MAX_BINARY_BYTES + 2048 }); }
  catch (_error) { throw new Error('Nasiko archive is invalid or exceeds the decompressed size limit.'); }
  let offset = 0;
  let binary = null;
  let terminated = false;
  while (offset < tar.length) {
    if (offset + 512 > tar.length) throw new Error('Unsafe Nasiko archive: truncated tar header.');
    const header = tar.subarray(offset, offset + 512);
    if (header.every(byte => byte === 0)) {
      const terminatorEnd = offset + 1024;
      if (
        terminatorEnd > tar.length
        || !tar.subarray(offset + 512, terminatorEnd).every(byte => byte === 0)
        || !tar.subarray(terminatorEnd).every(byte => byte === 0)
      ) {
        throw new Error('Unsafe Nasiko archive: incomplete terminator or nonzero trailing data.');
      }
      terminated = true;
      break;
    }

View on GitHub (pinned to 8321021c54)