can1357/oh-my-pi · error · ArchiveError

Tar numeric value does not fit its header field

Error message

Tar numeric value does not fit its header field

What it means

While encoding a tar header, a numeric field (size, mtime, mode, uid/gid) is written as zero-padded ASCII octal into a fixed-width header field. The library throws this when the value's octal representation has more digits than the field can hold (length-1 digits plus terminator). This prevents silently writing a truncated/corrupt tar header.

Source

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

	if (isZeroBlock(bytes, 0)) return true;
	try {
		if (readTarString(bytes, NAME_OFFSET, NAME_LENGTH).length === 0) return false;
		const size = readTarSize(bytes, SIZE_OFFSET);
		return Number.isSafeInteger(paddedSize(size)) && checksumMatches(bytes, 0);
	} catch {
		return false;
	}
}

function writeField(target: Uint8Array, offset: number, length: number, value: Uint8Array): void {
	if (value.byteLength > length) throw new ArchiveError("Tar header field is too long");
	target.set(value, offset);
}

function writeOctal(target: Uint8Array, offset: number, length: number, value: number): void {
	if (!Number.isSafeInteger(value) || value < 0) throw new ArchiveError("Invalid tar numeric value");
	const digits = value.toString(8);
	if (digits.length > length - 1) throw new ArchiveError("Tar numeric value does not fit its header field");
	for (let index = offset; index < offset + length - 1 - digits.length; index++) target[index] = 0x30;
	for (let index = 0; index < digits.length; index++)
		target[offset + length - 1 - digits.length + index] = digits.charCodeAt(index);
	target[offset + length - 1] = 0;
}

function splitUstarPath(pathBytes: Uint8Array): readonly [Uint8Array, Uint8Array] | undefined {
	if (pathBytes.byteLength <= NAME_LENGTH) return [pathBytes, new Uint8Array(0)];
	for (let index = pathBytes.byteLength - 1; index > 0; index--) {
		if (pathBytes[index] !== 0x2f) continue;
		const prefix = pathBytes.subarray(0, index);
		const name = pathBytes.subarray(index + 1);
		if (prefix.byteLength <= PREFIX_LENGTH && name.byteLength > 0 && name.byteLength <= NAME_LENGTH) {
			return [name, prefix];
		}
	}
	return undefined;
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Reduce member sizes below 8 GB or split large files before archiving
  2. Pass mtime in seconds, not milliseconds (Math.floor(ms / 1000))
  3. Verify size/mode/uid/gid values are the ustar-encoded numeric range expected
  4. Switch to an archive format without the ustar size limit (zip, or a tar writer with PAX/GNU extensions)

Example fix

// before
appendTarEntry(parts, path, hugeFileBytes, false, 0, { mtime: Date.now() });
// after
appendTarEntry(parts, path, hugeFileBytes, false, 0, { mtime: Math.floor(Date.now() / 1000) });
Defensive patterns

Strategy: validation

Validate before calling

const USTAR_SIZE_LIMIT = 0o77777777777; // 8 GB - 1
if (bytes.byteLength > USTAR_SIZE_LIMIT) {
	throw new Error(`Member '${path}' exceeds ustar size field (${bytes.byteLength} bytes)`);
}
const mtimeSec = Math.floor(mtimeMs / 1000);
if (!Number.isSafeInteger(mtimeSec) || mtimeSec < 0 || mtimeSec > 0o7777777777) {
	throw new Error(`mtime ${mtimeMs} out of ustar range`);
}

Try / catch

try {
	const tar = await createTar(members);
} catch (err) {
	if (err instanceof ArchiveError && err.message.includes("does not fit its header field")) {
		// split oversized members or use a different format
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling createTar (or appendTarEntry) with a file whose size exceeds the ustar size field limit (8 GB, since octal 77777777777 = 8589934591 bytes), an mtime beyond ~Oct 2242, or a uid/gid/mode too large for its field width.

Common situations: Archiving files larger than 8 GB with the ustar (not GNU/PAX) format; passing a Date.now()-in-milliseconds mtime instead of seconds; a corrupted or bogus size from a custom metadata source.

Related errors


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