can1357/oh-my-pi · error · ArchiveError
Invalid RPM package: truncated ${what} header
Error message
Invalid RPM package: truncated ${what} header What it means
ArchiveError thrown by validateHeaderBody() when the header body byte length does not equal intro.bodySize computed from the intro — the header was declared with indexCount and dataSize but fewer (or more) bytes were actually read. Guards against truncated headers before index entries are interpreted.
Source
Thrown at packages/utils/src/ar/rpm.ts:74
if (bytes.byteLength !== RPM_HEADER_INTRO_SIZE || readUInt32BE(bytes, 0) !== RPM_HEADER_MAGIC) {
throw new ArchiveError(`Invalid RPM package: corrupt ${what} header magic`);
}
for (let offset = 4; offset < 8; offset++) {
if (bytes[offset] !== 0) throw new ArchiveError(`Invalid RPM package: corrupt ${what} header reserved bytes`);
}
const indexCount = readUInt32BE(bytes, 8);
const dataSize = readUInt32BE(bytes, 12);
assertEntryCount(indexCount, options.limits);
const indexSize = indexCount * RPM_INDEX_ENTRY_SIZE;
const bodySize = indexSize + dataSize;
if (!Number.isSafeInteger(bodySize)) throw new ArchiveError(`Invalid RPM package: ${what} header is too large`);
assertIndexSize(RPM_HEADER_INTRO_SIZE + bodySize, options.limits, `RPM ${what} header`);
return { indexCount, dataSize, bodySize, totalSize: RPM_HEADER_INTRO_SIZE + bodySize };
}
function validateHeaderBody(body: Uint8Array, intro: HeaderIntro, what: string): void {
const indexSize = intro.indexCount * RPM_INDEX_ENTRY_SIZE;
if (body.byteLength !== intro.bodySize) throw new ArchiveError(`Invalid RPM package: truncated ${what} header`);
for (let index = 0; index < intro.indexCount; index++) {
const recordOffset = index * RPM_INDEX_ENTRY_SIZE;
const tag = readUInt32BE(body, recordOffset);
const type = readUInt32BE(body, recordOffset + 4);
const offset = readUInt32BE(body, recordOffset + 8);
const count = readUInt32BE(body, recordOffset + 12);
if (offset > intro.dataSize) throw new ArchiveError(`Invalid RPM package: tag ${tag} points outside header data`);
const remaining = intro.dataSize - offset;
let elementSize = 0;
if (type === 1 || type === 2 || type === 7) elementSize = 1;
else if (type === 3) elementSize = 2;
else if (type === 4) elementSize = 4;
else if (type === 5) elementSize = 8;
else if (type === 0) {
if (count !== 0) throw new ArchiveError(`Invalid RPM package: null tag ${tag} has values`);
continue;
} else if (type === RPM_TYPE_STRING || type === 8 || type === 9) {
const stringCount = type === RPM_TYPE_STRING ? 1 : count;View on GitHub (pinned to 9690622007)
Solutions
- Re-download the package and verify size
- Check disk/network integrity for the source file
- Validate the file end-to-end (e.g. rpm -K) outside the library to confirm corruption
Example fix
// before
const blob = await response.blob();
await readRpmArchive(await blob.arrayBuffer());
// after
const buf = new Uint8Array(await response.arrayBuffer());
if (buf.byteLength !== expectedSize) throw new Error(`short download: ${buf.byteLength}/${expectedSize}`);
await readRpmArchive(buf); Defensive patterns
Strategy: validation
Validate before calling
const expected = await fetchExpectedSizeFromRepoMetadata(url);
const actual = Bun.file(path).size;
if (actual !== expected) throw new Error(`incomplete download (${actual}/${expected})`); Type guard
null
Try / catch
try {
const rpm = await readRpmArchive(buf);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('truncated')) {
// prompt re-download
} else throw err;
} Prevention
- Always compare downloaded size with repository metadata
- Use resumable/checksummed downloads for large RPMs
- Parse only after the file is fully written to disk
When it happens
Trigger: Signature or main header read where the body read came up short relative to the intro's declared bodySize — truncated file, or the source ends mid-header.
Common situations: Partially downloaded .rpm files, source streams cut off mid-header, corrupt mirrors.
Related errors
- Invalid RPM package: truncated ${what}
- Invalid RPM package: truncated main header
- Invalid RPM package: truncated signature header
- ASAR member '${formatArchivePathForError(memberPath)}' is tr
- Invalid CAB archive: declared cabinet size is out of bounds
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/dbb61f27a4f8bce8.
Report an issue: GitHub.