can1357/oh-my-pi · error · ArchiveError
Unsupported RAR5 recovery record
Error message
Unsupported RAR5 recovery record
What it means
The RAR5 main archive header's archive flags bit 8 (RECOVERY) means the archive ends with a recovery record (RR) used to repair damaged archives. The library does not implement recovery-record parsing, so such archives are rejected.
Source
Thrown at packages/utils/src/ar/rar.ts:336
const headerStart = sizeCursor.offset;
const headerEnd = checkedEnd(headerStart, headerSize, bytes.byteLength, "RAR5 header");
if (crc32(bytes.subarray(sizeAt, headerEnd)) !== expectedHeaderCrc) corrupt("RAR5 header CRC32 mismatch");
const cursor = { offset: headerStart };
const type = readVint(bytes, cursor, headerEnd, "header type");
const flags = readVint(bytes, cursor, headerEnd, "header flags");
const extraSize = (flags & 1) !== 0 ? readVint(bytes, cursor, headerEnd, "extra area size") : 0;
const dataSize = (flags & 2) !== 0 ? readVint(bytes, cursor, headerEnd, "data size") : 0;
if ((flags & 0x18) !== 0) throw new ArchiveError("Unsupported multi-volume RAR5 archive");
const dataStart = headerEnd;
const dataEnd = checkedEnd(dataStart, dataSize, bytes.byteLength, "RAR5 data area");
if (extraSize > headerEnd - cursor.offset) corrupt("invalid RAR5 extra area size");
const extraStart = headerEnd - extraSize;
if (type === 4) throw new ArchiveError("Encrypted RAR5 headers are not supported");
if (type === 1) {
const archiveFlags = readVint(bytes, cursor, extraStart, "archive flags");
if ((archiveFlags & 1) !== 0) throw new ArchiveError("Unsupported multi-volume RAR5 archive");
if ((archiveFlags & 8) !== 0) throw new ArchiveError("Unsupported RAR5 recovery record");
if ((archiveFlags & 2) !== 0) readVint(bytes, cursor, extraStart, "volume number");
sawMain = true;
} else if (type === 2 || type === 3) {
const fileFlags = readVint(bytes, cursor, extraStart, "file flags");
const unpackedSize = readVint(bytes, cursor, extraStart, "unpacked size");
if ((fileFlags & 8) !== 0) throw new ArchiveError("RAR5 member with unknown unpacked size is not supported");
const attributes = readVint(bytes, cursor, extraStart, "file attributes");
let mtimeMs: number | undefined;
if ((fileFlags & 2) !== 0) {
need(cursor.offset, 4, extraStart, "RAR5 modification time");
mtimeMs = readUInt32LE(bytes, cursor.offset) * 1000;
cursor.offset += 4;
}
let dataCrc: number | undefined;
if ((fileFlags & 4) !== 0) {
need(cursor.offset, 4, extraStart, "RAR5 data CRC32");
dataCrc = readUInt32LE(bytes, cursor.offset);
cursor.offset += 4;View on GitHub (pinned to 9690622007)
Solutions
- Re-create the archive without the recovery record option
- Strip the recovery record with `rar rr` tooling or re-save with WinRAR/unrar
- Parse an RR-free copy; the actual file data is unaffected
Example fix
// before rar a -rr backup.rar files/ // creates RR the parser rejects // after rar a backup.rar files/ // no recovery record
Defensive patterns
Strategy: try-catch
Try / catch
try {
const records = readRar(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('recovery record')) {
logger.warn('RAR has recovery record; parsing not supported');
} else throw err;
} Prevention
- Create archives without -rr / 'Add recovery record' for programmatic use
- Note that RR only helps repair; it is not needed to read intact archives
When it happens
Trigger: Reading a RAR5 archive created with the recovery record option (WinRAR 'Add recovery record', `rar -rr`, or `rar rr` applied afterwards).
Common situations: Archives intended for flaky transfer media (email, Usenet, optical discs); downloaded releases that ship .rev recovery data; backup policies mandating RR.
Related errors
- Unsupported multi-volume RAR5 archive
- Unsupported RAR4 recovery record
- ARJ member '${memberPath}' uses unsupported compression meth
- Encrypted ARJ archives are unsupported
- Multi-volume ARJ archives are unsupported
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ea705961a6851bc4.
Report an issue: GitHub.