can1357/oh-my-pi · error · ArchiveError
Invalid ZIP archive: truncated extra-field header
Error message
Invalid ZIP archive: truncated extra-field header
What it means
Thrown by parseExtra when, while iterating an entry's extra-field blob as a sequence of (id:u16, size:u16, data) records, fewer than 4 bytes remain where a record header is expected. The extra-field region ends mid-header, so it cannot be parsed.
Source
Thrown at packages/utils/src/ar/zip.ts:259
function parseDosMtime(time: number, date: number): number | undefined {
if (date === 0) return undefined;
const year = 1980 + ((date >>> 9) & 0x7f);
const month = ((date >>> 5) & 0x0f) - 1;
const day = date & 0x1f;
const hour = (time >>> 11) & 0x1f;
const minute = (time >>> 5) & 0x3f;
const second = (time & 0x1f) * 2;
if (month < 0 || month > 11 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) return undefined;
const value = new Date(year, month, day, hour, minute, second).getTime();
return Number.isFinite(value) ? value : undefined;
}
function parseExtra(extra: Uint8Array, rawName: Uint8Array): ParsedExtra {
const result: ParsedExtra = {};
let offset = 0;
while (offset < extra.byteLength) {
if (offset + 4 > extra.byteLength) throw new ArchiveError("Invalid ZIP archive: truncated extra-field header");
const id = readUInt16LE(extra, offset);
const size = readUInt16LE(extra, offset + 2);
const dataStart = offset + 4;
const dataEnd = dataStart + size;
if (dataEnd > extra.byteLength) throw new ArchiveError("Invalid ZIP archive: malformed extra field");
const data = extra.subarray(dataStart, dataEnd);
if (id === 0x0001) {
result.zip64 = data;
} else if (id === 0x7075) {
if (data.byteLength < 5) throw new ArchiveError("Invalid ZIP archive: Unicode path extra field is too small");
if (data[0] === 1 && readUInt32LE(data, 1) === crc32(rawName)) {
try {
result.unicodePath = UTF8_FATAL_DECODER.decode(data.subarray(5));
} catch {
// A bad optional Unicode path falls back to the header name.
}
}
} else if (id === 0x5455) {View on GitHub (pinned to 9690622007)
Solutions
- Validate with `unzip -t` / `zipinfo -v` to see which entry has inconsistent extra-field lengths.
- Re-zip the archive with a standard tool to regenerate consistent headers.
- Repair with `zip -FF` if the archive is otherwise valuable.
- If you control the writer, ensure every extra record is exactly 4+size bytes and extra_field_length equals the sum.
Example fix
// before: trusting a third-party writer's output
const zip = readZip(legacyToolZip);
// after: rebuild with a canonical writer
await $`unzip -q legacyTool.zip -d tmp`;
await $`zip -qr fixed.zip .`.cwd("tmp");
const zip = readZip("fixed.zip"); Defensive patterns
Strategy: try-catch
Validate before calling
const probe = Bun.spawnSync(["zipinfo", path]);
if (probe.exitCode !== 0) throw new Error(`zip headers inconsistent (zipinfo failed); re-zip before reading: ${path}`); Try / catch
try {
const zip = readZip(path);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("truncated extra-field header")) {
// rebuild to regenerate consistent extra fields
await $`unzip -q ${path} -d tmp`; await $`zip -qr fixed.zip .`.cwd("tmp");
return readZip("fixed.zip");
}
throw err;
} Prevention
- Avoid zip writers that pad or hand-assemble extra fields; test their output with `zipinfo -v`.
- Never modify extra_field_length without rewriting the contained records.
- Checksum-verify archives from untrusted sources before parsing.
- Route all zip production through one canonical tool in your pipeline.
When it happens
Trigger: Calling zip info/read on an archive where a central-directory or local-header extra field's total length leaves 1–3 trailing bytes, i.e. the extra_field_length in the surrounding header does not match the sum of contained record sizes.
Common situations: Archives produced by writers that pad extra fields incorrectly; corrupted archives where a record's size field was altered; zip files modified in place by tools that rewrote lengths inconsistently.
Related errors
- Invalid ZIP archive: malformed NTFS extra field
- Invalid ZIP archive: malformed extra field
- Invalid ZIP archive: central directory is out of bounds or m
- Invalid ZIP archive: missing ZIP64 central-directory metadat
- Invalid ZIP archive: truncated central directory
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fbdcbe96b1102413.
Report an issue: GitHub.