can1357/oh-my-pi · error · ArchiveError
Invalid RPM package: bad lead magic
Error message
Invalid RPM package: bad lead magic
What it means
readRpmArchive reads the first 96-byte RPM lead plus header intro and checks the lead magic (0xEDABEEDB via sniffRpm). If the bytes do not match, the file is not an RPM package at all, so the reader fails fast before any parsing.
Source
Thrown at packages/utils/src/ar/rpm.ts:247
return xzDecompress(payload, maxOutput);
case "zstd":
case "zstdio":
return zstdDecompress(payload, maxOutput);
case "lzma":
if (!sniffLzmaAlone(payload)) throw new ArchiveError(`RPM package '${identity}' has a malformed LZMA payload`);
return lzmaAloneDecompress(payload, maxOutput);
case "none":
if (!sniffCpio(payload))
throw new ArchiveError(`RPM package '${identity}' has an invalid uncompressed CPIO payload`);
return payload;
default:
throw new ArchiveError(`RPM package '${identity}' uses unsupported payload compressor '${method}'`);
}
}
async function readRpmArchive(source: ByteSource, options: FormatReadOptions): Promise<ArchiveIndexEntry[]> {
const initial = await readExact(source, 0, RPM_LEAD_SIZE + RPM_HEADER_INTRO_SIZE, "lead and signature header");
if (!sniffRpm(initial)) throw new ArchiveError("Invalid RPM package: bad lead magic");
const major = initial[4]!;
const packageType = (initial[6]! << 8) | initial[7]!;
if (major < 3 || packageType > 1) throw new ArchiveError("Unsupported RPM package lead version or type");
const signatureType = (initial[78]! << 8) | initial[79]!;
if (signatureType !== RPM_SIGNATURE_TYPE_HEADER) {
throw new ArchiveError(`Unsupported RPM signature type ${signatureType}; only header signatures are supported`);
}
const leadNameEnd = initial.subarray(10, 76).indexOf(0);
const leadNameBytes = initial.subarray(10, leadNameEnd < 0 ? 76 : 10 + leadNameEnd);
let leadName = "unknown package";
try {
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(leadNameBytes);
if (decoded) leadName = decoded;
} catch {}
const signatureIntro = parseHeaderIntro(initial.subarray(RPM_LEAD_SIZE), options, "signature");
const signatureEnd = RPM_LEAD_SIZE + signatureIntro.totalSize;
const mainHeaderOffset = align(signatureEnd, 8);View on GitHub (pinned to 9690622007)
Solutions
- Verify the file path/URL actually points to an RPM; check the first bytes with `file <path>` — it should report 'RPM v3/v4'.
- Inspect the start of the response: if it's HTML, fix the download URL (mirror 404/redirect) and re-download.
- Ensure you are using the RPM reader and not passing a .deb/.tar.gz to it; route each file to the right format reader.
- Checksum-verify the download to confirm you got the real package.
Example fix
// before
const entries = await readRpm(maybeRpmPath);
// after: sniff before parsing
const head = new Uint8Array(await Bun.file(path).slice(0, 4).arrayBuffer());
if (!(head[0] === 0xed && head[1] === 0xab && head[2] === 0xee && head[3] === 0xdb)) throw new Error('not an RPM file'); Defensive patterns
Strategy: validation
Validate before calling
export async function isRpmFile(path: string): Promise<boolean> {
const b = new Uint8Array(await Bun.file(path).slice(0, 4).arrayBuffer());
return b[0] === 0xed && b[1] === 0xab && b[2] === 0xee && b[3] === 0xdb;
}
// call before readRpm Type guard
function isRpmLead(head: Uint8Array): boolean {
return head.length >= 4 && head[0] === 0xed && head[1] === 0xab && head[2] === 0xee && head[3] === 0xdb;
} Try / catch
try {
return await readRpm(path);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('bad lead magic')) {
throw new Error(`${path} is not an RPM file (bad magic); check path/download`);
}
throw err;
} Prevention
- Sniff magic bytes (or run `file`) before dispatching to a format reader.
- Check downloaded file sizes/HTML bodies to catch mirror 404 pages saved as .rpm.
- Validate content-type and checksums on downloads.
When it happens
Trigger: Calling the RPM reader (readRpm/metadata) on a file whose first four bytes are not the RPM lead magic — e.g. a .deb, a tarball, an HTML error page saved as .rpm, or an empty/zero-byte file path.
Common situations: Pointing the reader at the wrong file (deb vs rpm), downloading a mirror's 404 page instead of the package, passing a source RPM stream that was already partially consumed, or a URL redirect to a login page.
Related errors
- Invalid EPUB: missing container.xml
- Invalid EPUB: missing rootfile path
- Invalid EPUB: missing content.opf
- Invalid PPTX: missing presentation.xml
- Invalid XLSX: missing workbook.xml
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f531af28846b0188.
Report an issue: GitHub.