can1357/oh-my-pi · error · ArchiveError

Encrypted RAR5 headers are not supported

Error message

Encrypted RAR5 headers are not supported

What it means

RAR5 header type 4 is the encryption header, present when archive headers themselves are encrypted (password-protected archive with the 'encrypt file names' option). The library cannot parse any subsequent headers without the password, so it rejects the archive outright.

Source

Thrown at packages/utils/src/ar/rar.ts:332

		const sizeCursor = { offset: sizeAt };
		const headerSize = readVint(bytes, sizeCursor, bytes.byteLength, "header size");
		if (headerSize > 2 * 1024 * 1024) corrupt("RAR5 header exceeds format limit");
		assertIndexSize(headerSize, options.limits, "RAR5 header");
		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;

View on GitHub (pinned to 9690622007)

Solutions

  1. Decrypt the archive first with the unrar CLI (`unrar x -p<password> file.rar`) and parse the output
  2. Re-create the archive without header/filename encryption
  3. Detect password-protected archives upstream and route them to a tool that supports passwords

Example fix

// before
const records = readRar(await Bun.file('secret.rar').bytes());
// after
// decrypt externally first:
await $`unrar x -p${password} secret.rar outdir/`;
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const records = readRar(bytes);
} catch (err) {
  if (err instanceof ArchiveError && /encrypted/i.test(err.message)) {
    throw new Error('Archive is password-protected; supply a password via external extraction');
  } else throw err;
}

Prevention

When it happens

Trigger: Reading a RAR5 archive created with 'Encrypt file names' checked in WinRAR (or -hp flag on the rar CLI); the parser encounters header type 4 while walking headers.

Common situations: Password-protected archives with hidden file lists from users or third parties; security-focused uploads where filename encryption was enabled; automation processing user-supplied RAR files.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b543cd1979622c9a. Report an issue: GitHub.