can1357/oh-my-pi · error · ArchiveError

Not a valid tar archive: missing terminating zero block

Error message

Not a valid tar archive: missing terminating zero block

What it means

This library validates that a tar archive ends with the two consecutive 512-byte zero blocks required by the tar format. If it reaches the end of the data without having seen that terminator, it refuses to index the archive and throws this ArchiveError. It is a structural integrity check: tar archives without the terminator are considered malformed or truncated, not merely odd.

Source

Thrown at packages/utils/src/ar/tar.ts:573

				entry.storage = { type: "link", targetPath: portableLinkName, resolveTarget: false };
				addEntry(entry);
				continue;
			}
			addEntry(entry, { kind, targetPath });
			continue;
		}
		if (typeFlag !== "0" && typeFlag !== "\0" && typeFlag !== "7" && typeFlag !== "S") continue;
		assertArchiveMemberSize(displaySize, normalizedPath, limits);
		addEntry({
			path: normalizedPath,
			isDirectory: false,
			size: displaySize,
			mtimeMs,
			mode,
			storage: { type: "member", source: new TarMemberSource(buffer, dataOffset, sparse) },
		});
	}
	if (!sawTerminator) throw new ArchiveError("Not a valid tar archive: missing terminating zero block");
	resolvePendingLinks(entries, pendingLinks, limits);
	return [...entries.values()];
}

/** Read and index a tar source after one bounded whole-stream read. */
export const readTar: FormatReader = async (source, options) => {
	assertInMemorySize(source.size, options.limits);
	let bytes: Uint8Array;
	try {
		bytes = await readAllBytes(source);
	} catch (error) {
		if (error instanceof ArchiveError) throw error;
		throw new ArchiveError(error instanceof Error ? error.message : "Failed to read tar archive");
	}
	if (bytes.byteLength !== source.size) throw new ArchiveError("Invalid archive: truncated data");
	return readTarEntriesFromBuffer(bytes, options);
};

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-obtain or re-extract the archive; the source is truncated — verify byte size against the upstream checksum
  2. Rebuild the tar with a standard tool (`tar -cf`) so the terminating zero blocks are written
  3. Pad the buffer manually with two 512-byte zero blocks if you control generation and know the data is otherwise complete
  4. Check the producer: if you write tars yourself, append two zeroed 512-byte blocks after the last member

Example fix

// before: hand-rolled writer omits the terminator
blocks.push(...memberBlocks);
await Bun.write(out, blocks);
// after: append the required two zero blocks
const terminator = new Uint8Array(2 * 512);
await Bun.write(out, [blocks, terminator]);
Defensive patterns

Strategy: validation

Validate before calling

function isTerminatedTar(bytes: Uint8Array): boolean {
  if (bytes.byteLength % 512 !== 0) return false;
  const end = bytes.byteLength - 1024;
  if (end < 0) return false;
  return bytes.subarray(end).every((b) => b === 0);
}
if (!isTerminatedTar(bytes)) throw new Error("tar archive lacks terminating zero blocks");

Try / catch

try {
  const entries = await readTar(source, options);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes("missing terminating zero block")) {
    // treat as corrupted/truncated download: re-fetch or surface to user
  } else throw err;
}

Prevention

When it happens

Trigger: Calling readTar (or readTarEntriesFromBuffer) on a byte buffer that ends after the last file's data blocks without the terminating zero blocks — e.g. a tar written by a custom/naive writer, a stream cut off mid-archive, or a tar concatenated with padding stripped.

Common situations: Downloads interrupted before completion, pipes closed early (curl ... | tar-like flows captured partially), hand-rolled tar writers that forget the terminator, archives produced by tools emitting 'streaming' tar without end-of-archive markers, files truncated on disk after a crash.

Related errors


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