can1357/oh-my-pi · error · ArchiveError
Tar header field is too long
Error message
Tar header field is too long
What it means
When writing (serializing) a tar header, each field occupies a fixed number of bytes. writeField throws this ArchiveError if the value bytes exceed the field's fixed length. This guards against silently producing a corrupt archive with overlapping fields.
Source
Thrown at packages/utils/src/ar/tar.ts:606
if (bytes.byteLength !== source.size) throw new ArchiveError("Invalid archive: truncated data");
return readTarEntriesFromBuffer(bytes, options);
};
/** Detect a tar header, including legacy pre-ustar archives, by its checksum. */
export function sniffTar(bytes: Uint8Array): boolean {
if (bytes.byteLength < BLOCK_SIZE) return false;
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);View on GitHub (pinned to 9690622007)
Solutions
- Let the writer emit PAX (pax_header) records for long paths instead of forcing plain ustar layout
- Shorten the member path before writing (strip or rebase the leading directories)
- If writing manually, split the path into prefix/name via splitUstarPath logic, or use GNU longname ('././@LongLink') extension
- Check the encoded byte length (Buffer.byteLength, not string length) against the field limit before writing
Example fix
// before: long path blows the 100-byte name field
addEntry({ path: `very/long/${repeat}/file.txt`, ... });
// after: rebase so the stored path fits
addEntry({ path: `very/long/${repeat}/file.txt`.replace(/^very\/long\//, ""), ... }); Defensive patterns
Strategy: validation
Validate before calling
const encoded = Buffer.byteLength(entryPath, "utf-8");
if (encoded > 100) {
// ensure the writer supports pax/GNU long names, or shorten the path first
} Prevention
- Keep member paths under 100 bytes or rely on the ustar prefix split (prefix <=155, name >0 and <=100)
- Prefer writers that auto-emit PAX records for long names
- Measure paths in bytes (UTF-8), not characters
When it happens
Trigger: Calling the tar writer with a name, link name, or other field whose UTF-8 encoding is longer than the fixed header slot (e.g. name > 100 bytes for plain ustar when no prefix split or pax record is applied).
Common situations: Very long file paths or deep directory trees written without ustar prefix splitting or GNU/pax long-name extension; long symlink targets; usernames/groupnames over 32 bytes.
Related errors
- Invalid tar numeric value
- Writer closed
- Invalid tar octal value: ${value}
- Truncated embedded addon archive entry: ${filename}
- Unsafe embedded addon archive entry: ${filename}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e4136275f1f89cb5.
Report an issue: GitHub.