{"record":{"id":"ddda9af2bf47a4ff","repo":"can1357/oh-my-pi","slug":"invalid-rpm-package-corrupt-what-header-magic","errorCode":null,"errorMessage":"Invalid RPM package: corrupt ${what} header magic","messagePattern":"Invalid RPM package: corrupt (.+?) header magic","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rpm.ts","lineNumber":57,"sourceCode":"}\n\nfunction align(value: number, alignment: number): number {\n\tconst remainder = value % alignment;\n\treturn remainder === 0 ? value : value + alignment - remainder;\n}\n\nasync function readExact(source: ByteSource, start: number, end: number, what: string): Promise<Uint8Array> {\n\tif (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start || end > source.size) {\n\t\tthrow new ArchiveError(`Invalid RPM package: truncated ${what}`);\n\t}\n\tconst bytes = await source.read(start, end);\n\tif (bytes.byteLength !== end - start) throw new ArchiveError(`Invalid RPM package: truncated ${what}`);\n\treturn bytes;\n}\n\nfunction parseHeaderIntro(bytes: Uint8Array, options: FormatReadOptions, what: string): HeaderIntro {\n\tif (bytes.byteLength !== RPM_HEADER_INTRO_SIZE || readUInt32BE(bytes, 0) !== RPM_HEADER_MAGIC) {\n\t\tthrow new ArchiveError(`Invalid RPM package: corrupt ${what} header magic`);\n\t}\n\tfor (let offset = 4; offset < 8; offset++) {\n\t\tif (bytes[offset] !== 0) throw new ArchiveError(`Invalid RPM package: corrupt ${what} header reserved bytes`);\n\t}\n\tconst indexCount = readUInt32BE(bytes, 8);\n\tconst dataSize = readUInt32BE(bytes, 12);\n\tassertEntryCount(indexCount, options.limits);\n\tconst indexSize = indexCount * RPM_INDEX_ENTRY_SIZE;\n\tconst bodySize = indexSize + dataSize;\n\tif (!Number.isSafeInteger(bodySize)) throw new ArchiveError(`Invalid RPM package: ${what} header is too large`);\n\tassertIndexSize(RPM_HEADER_INTRO_SIZE + bodySize, options.limits, `RPM ${what} header`);\n\treturn { indexCount, dataSize, bodySize, totalSize: RPM_HEADER_INTRO_SIZE + bodySize };\n}\n\nfunction validateHeaderBody(body: Uint8Array, intro: HeaderIntro, what: string): void {\n\tconst indexSize = intro.indexCount * RPM_INDEX_ENTRY_SIZE;\n\tif (body.byteLength !== intro.bodySize) throw new ArchiveError(`Invalid RPM package: truncated ${what} header`);\n\tfor (let index = 0; index < intro.indexCount; index++) {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rpm.ts#L39-L75","documentation":"ArchiveError thrown by parseHeaderIntro() when an RPM header intro (signature or main) fails validation: the intro is not exactly RPM_HEADER_INTRO_SIZE bytes or its first 4 bytes are not the RPM header magic (0x8eade801). Indicates the byte stream is not where an RPM header should be.","triggerScenarios":"Parsing the signature or main header intro whose bytes don't begin with the RPM header magic — wrong offset computed from the lead, file is not an RPM, or the header region is corrupted/overwritten.","commonSituations":"Non-RPM files renamed to .rpm, corrupted downloads, misaligned leads from hand-crafted or exotic packages (e.g. unusual padding).","solutions":["Verify the file is a genuine .rpm (check the RPM lead magic first)","Re-download the package","Check for leading bytes/offset drift if you wrapped the source (e.g. skipped the lead incorrectly)"],"exampleFix":"// before\nawait readRpmArchive(buffer.subarray(claimedOffset));\n// after\n// pass the full, unshifted buffer — the reader computes the lead/header offsets itself\nawait readRpmArchive(buffer);","handlingStrategy":"validation","validationCode":"const lead = new Uint8Array(buf, 0, 4);\nconst isRpm = lead[0] === 0xed && lead[1] === 0xab && lead[2] === 0xee && lead[3] === 0xdb;\nif (!isRpm) throw new Error('not an RPM package');","typeGuard":"function isRpmBuffer(buf: Uint8Array): boolean {\n  return buf.byteLength >= 4 && buf[0] === 0xed && buf[1] === 0xab && buf[2] === 0xee && buf[3] === 0xdb;\n}","tryCatchPattern":"try {\n  const rpm = await readRpmArchive(buf);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes('header magic')) {\n    // report 'file is not a valid RPM' to the caller\n  } else throw err;\n}","preventionTips":["Check the RPM lead magic (ed ab ee db) before parsing","Never pass user-renamed files to the RPM reader without sniffing content","Verify checksums from a trusted index"],"tags":["rpm","archive","magic-number","corrupt-file"],"backgroundTag":"invalid-file-magic","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}