{"record":{"id":"1b6c2d2b7b23e878","repo":"can1357/oh-my-pi","slug":"invalid-rar-archive-reason","errorCode":null,"errorMessage":"Invalid RAR archive: ${reason}","messagePattern":"Invalid RAR archive: (.+?)","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rar.ts","lineNumber":734,"sourceCode":"\nfunction filetimeMs(bytes: Uint8Array, offset: number): number {\n\tconst ticks = readUInt32LE(bytes, offset) + readUInt32LE(bytes, offset + 4) * 0x100000000;\n\treturn ticks / 10000 - 11644473600000;\n}\n\nfunction checkedEnd(start: number, size: number, limit: number, what: string): number {\n\tif (!Number.isSafeInteger(start) || !Number.isSafeInteger(size) || size < 0) corrupt(`invalid ${what} range`);\n\tconst end = start + size;\n\tif (!Number.isSafeInteger(end) || end < start || end > limit) corrupt(`truncated ${what}`);\n\treturn end;\n}\n\nfunction need(start: number, size: number, end: number, what: string): void {\n\tcheckedEnd(start, size, end, what);\n}\n\nfunction corrupt(reason: string): never {\n\tthrow new ArchiveError(`Invalid RAR archive: ${reason}`);\n}\n","sourceCodeStart":716,"sourceCodeEnd":736,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rar.ts#L716-L736","documentation":"Generic corruption guard for RAR archives: `corrupt(reason)` throws ArchiveError(\"Invalid RAR archive: <reason>\") whenever structural parsing assumptions fail — bad signatures, truncated headers, out-of-bounds offsets, missing mandatory headers (e.g. 'RAR4 main header is missing'). The interpolated `reason` names the specific structural problem found (packages/utils/src/ar/rar.ts:734).","triggerScenarios":"Any call that parses RAR data (listing, reading entries) when the byte stream violates RAR structure: truncated download, flipped/invalid signature bytes, offsets running past buffer end via `need()`/`checkedEnd()`, missing RAR4 main header, or malformed header fields.","commonSituations":"Incomplete HTTP download or interrupted transfer; archive corrupted in storage/transit; someone renamed a non-RAR file to .rar; text-mode (FTP/ASCII) transfer mangling binary data; edited or partially deleted archive file.","solutions":["Re-download or re-copy the archive and verify its checksum/hash matches the source.","Validate the archive externally (`unrar t archive.rar` or `7z t archive.rar`) to confirm it opens elsewhere; if it doesn't, the file is corrupt, not a library issue.","Confirm the file is actually a RAR (magic bytes: Rar!\\x1a\\x07 for RAR4/RAR5) and wasn't renamed from another format.","Check transfer mode — re-transfer over binary mode (FTP binary, no text transformations).","Catch ArchiveError, inspect the `reason` suffix, and surface it to the user so they can repair/re-obtain the archive."],"exampleFix":"// before: trusting an unverified download\nconst reader = await openArchive(archivePath);\n\n// after: verify integrity before parsing\nconst ok = await $`7z t ${archivePath}`.quiet().nothrow();\nif (ok.exitCode !== 0) throw new Error(`${archivePath} failed integrity check; re-download it`);\nconst reader = await openArchive(archivePath);","handlingStrategy":"try-catch","validationCode":"// Verify magic bytes + transfer integrity before parsing\nconst sig = new Uint8Array(await Bun.file(p).slice(0, 7).arrayBuffer());\nconst validSig = sig[0] === 0x52 && sig[1] === 0x61 && sig[2] === 0x72 && sig[3] === 0x21 && sig[4] === 0x1a && sig[5] === 0x07;\nif (!validSig) throw new Error(`${p} is not a RAR archive (bad signature)`);\n// optionally: const t = await $`unrar t ${p}`.quiet().nothrow(); if (t.exitCode !== 0) throw ...","typeGuard":"function isRarMagic(bytes: Uint8Array): boolean {\n  return bytes.length >= 6 &&\n    bytes[0] === 0x52 && bytes[1] === 0x61 && bytes[2] === 0x72 &&\n    bytes[3] === 0x21 && bytes[4] === 0x1a && bytes[5] === 0x07;\n}","tryCatchPattern":"try {\n  const reader = await openArchive(p);\n  return reader;\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.startsWith('Invalid RAR archive:')) {\n    throw new Error(`${p} is corrupt (${err.message}); re-download and verify its checksum`);\n  }\n  throw err;\n}","preventionTips":["Verify checksums/hashes after every download before parsing.","Check the Rar! magic bytes before opening.","Use binary-safe transfer (no text-mode FTP/ASCII conversion).","Run `unrar t` / `7z t` as a pre-flight integrity gate in pipelines."],"tags":["archive","rar","corruption","malformed-input"],"backgroundTag":"archive-corrupt","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}