can1357/oh-my-pi · error · Error

Truncated embedded addon archive entry: ${filename}

Error message

Truncated embedded addon archive entry: ${filename}

What it means

While walking the gunzipped tar stream of the embedded addon archive, the loader reads each 512-byte header and its octal size at offset 124. If offset + size exceeds the archive buffer length, the entry's payload is not fully present and the loader throws instead of writing a truncated .node file.

Source

Thrown at packages/natives/native/loader-state.js:523

			pending.set(file.filename, file);
		}
	}
	if (pending.size === 0) return [];

	const archive = zlib.gunzipSync(fs.readFileSync(archivePath));
	const writtenPaths = [];
	let offset = 0;

	while (offset + 512 <= archive.length) {
		if (isZeroTarBlock(archive, offset)) break;
		const header = archive.subarray(offset, offset + 512);
		const filename = getTarEntryName(header);
		const size = readTarOctal(header, 124, 12);
		const typeflag = header[156] === 0 ? "0" : String.fromCharCode(header[156]);
		offset += 512;

		if (offset + size > archive.length) {
			throw new Error(`Truncated embedded addon archive entry: ${filename}`);
		}

		if (!isSafeEmbeddedAddonFilename(filename)) {
			throw new Error(`Unsafe embedded addon archive entry: ${filename}`);
		}
		if (typeflag !== "0") {
			throw new Error(`Unsupported embedded addon archive entry type ${typeflag}: ${filename}`);
		}

		const file = pending.get(filename);
		if (file) {
			if (typeof file.size === "number" && file.size !== size) {
				throw new Error(`Embedded addon size mismatch for ${filename}: expected ${file.size}, got ${size}`);
			}
			const targetPath = path.join(targetDir, filename);
			writeEmbeddedAddonFile(targetPath, archive.subarray(offset, offset + size));
			pending.delete(filename);
			writtenPaths.push(targetPath);

View on GitHub (pinned to 9690622007)

Solutions

  1. Reinstall omp / rebuild the binary so the embedded archive is regenerated intact.
  2. Verify the archive file: gunzip -t then tar -tzf to confirm it is complete and well-formed.
  3. Check the build pipeline that produces the .tar.gz asset for truncation (e.g. interrupted copy, size mismatch in packaging).
  4. As a caller, delete any cached extracted files and retry extraction from a known-good binary.
Defensive patterns

Strategy: fallback

Validate before calling

import * as zlib from "node:zlib";
import * as fs from "node:fs";
function validateArchiveIntegrity(archivePath) {
  const tar = zlib.gunzipSync(fs.readFileSync(archivePath));
  let offset = 0;
  while (offset + 512 <= tar.length && !isZeroBlock(tar, offset)) {
    const size = parseInt(tar.toString("utf8", offset + 124, offset + 136).replace(/\0.*$/, "").trim(), 16) || 0;
    offset += 512 + Math.ceil(size / 512) * 512;
  }
  return offset <= tar.length; // false => truncated archive
}

Try / catch

try {
  extractEmbeddedAddonArchive({ archivePath, files, targetDir });
} catch (err) {
  if (String(err.message).startsWith("Truncated embedded addon archive entry:")) {
    // fall back to on-disk node_modules copy or trigger reinstall
  } else throw err;
}

Prevention

When it happens

Trigger: Calling extractEmbeddedAddonArchive where the .tar.gz decoded to fewer bytes than the tar headers claim: the last (or a middle) entry's declared size runs past the end of the decompressed buffer. Raised during the header walk, before any per-entry validation or write.

Common situations: A truncated or partially downloaded/corrupted archive file embedded in the binary; a build step that produced an incomplete .tar.gz; disk corruption; someone concatenating or editing the archive bytes.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/57df9c3ca6362c3f. Report an issue: GitHub.