affaan-m/ECC · error · Error

Unsafe Nasiko archive: invalid tar size field.

Error message

Unsafe Nasiko archive: invalid tar size field.

What it means

readTarOctal parses a tar header size field, which must be space-padded octal digits. This error (thrown at the regex check) means the field does not match the expected tar numeric format, so the archive header is corrupt or not a real tar header. It is part of the library's defensive extraction of the gzip artifact.

Solutions

  1. Gunzip the archive manually and hexdump the first 512 bytes to confirm it is a real tar header with an octal size at offset 124.
  2. Re-download the artifact — corruption mid-transfer is the most common cause.
  3. If the producer uses GNU base-256 size encoding, repack with `tar --format=ustar` so sizes stay ASCII octal.
  4. Verify you are not accidentally passing the gzip bytes where tar bytes are expected (double-gunzip).

Example fix

// before
// extractQualifiedTarGzip(artifact) -> invalid tar size field
// after
const tar = zlib.gunzipSync(fs.readFileSync('artifact.gz'));
console.log(tar.subarray(0, 512).toString('hex').slice(0, 200)); // inspect header
// repack if needed:
// tar --format=ustar -cf artifact.tar bin/ && gzip artifact.tar
Defensive patterns

Strategy: validation

Validate before calling

const tar = zlib.gunzipSync(archiveBytes);
if (tar.length % 512 !== 0) throw new Error('tar length not block-aligned');
const sizeField = tar.subarray(124, 136).toString('ascii');
if (!/^ *([0-7]+)[ \0]*$/.test(sizeField)) throw new Error('first header not a ustar tar header');

Type guard

const isUstarHeader = (tar) => /^ *([0-7]+)[ \0]*$/.test(tar.subarray(124, 136).toString('ascii'));

Try / catch

try { installNasiko(opts); } catch (e) { if (e.message.includes('invalid tar size field')) console.error('archive is not a plain ustar tar; repack with --format=ustar'); throw e; }

Prevention

When it happens

Trigger: extractQualifiedTarGzip walks 512-byte tar blocks and calls readTarOctal on a header whose size field contains non-octal bytes — e.g. the gunzipped data is not a tar at all, the header offset drifted, or the file uses a non-standard numeric format (base-256 GNU extension the regex rejects).

Common situations: Extracting an artifact that is gzip but not tar (bare binary gzipped), a corrupted download, or a GNU/sparse tar feature that encodes size in base-256 binary instead of ASCII octal.

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/ecc89fe56c9fab02. Report an issue: GitHub.

Appendix: source

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

  }
  const layer = manifest.layers[0];
  if (layer.mediaType !== 'application/gzip' || !SHA256_PATTERN.test(layer.digest)) {
    throw new Error('Nasiko manifest layer is not a qualified gzip artifact.');
  }
  if (!Number.isSafeInteger(layer.size) || layer.size <= 0 || layer.size > MAX_ARCHIVE_BYTES) {
    throw new Error('Nasiko manifest layer size is outside the allowed range.');
  }
  return { digest: layer.digest, size: layer.size };
}

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)) {

View on GitHub (pinned to 8321021c54)