can1357/oh-my-pi · error · ArchiveError

RAR5 dictionary is too large (${dictionarySize} bytes)

Error message

RAR5 dictionary is too large (${dictionarySize} bytes)

What it means

Each RAR5 compressed member declares a LZ dictionary size derived from the compression-info bits (128 KiB * 2^power, optionally extended). If the computed dictionary is not a safe integer or exceeds options.limits.maxInMemorySize, the library refuses because members are decompressed in memory.

Source

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

				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;
			}
			const compression = readVint(bytes, cursor, extraStart, "compression information");
			let version = compression & 0x3f;
			if (version === 1 && (compression & 0x100000) !== 0) version = 0;
			const solid = (compression & 0x40) !== 0;
			const method = (compression >>> 7) & 7;
			const dictionaryPower = (compression >>> 10) & 0x1f;
			let dictionarySize = 128 * 1024 * 2 ** dictionaryPower;
			if ((compression & 0x3f) === 1) dictionarySize += (dictionarySize * ((compression >>> 15) & 0x1f)) / 32;
			if (!Number.isSafeInteger(dictionarySize) || dictionarySize > options.limits.maxInMemorySize) {
				throw new ArchiveError(`RAR5 dictionary is too large (${dictionarySize} bytes)`);
			}
			const hostOs = readVint(bytes, cursor, extraStart, "host OS");
			const nameSize = readVint(bytes, cursor, extraStart, "file name size");
			assertArchivePathBytes(nameSize, "member path", options.limits.maxPathBytes);
			need(cursor.offset, nameSize, extraStart, "RAR5 file name");
			let rawPath: string;
			try {
				rawPath = UTF8.decode(bytes.subarray(cursor.offset, cursor.offset + nameSize));
			} catch {
				throw new ArchiveError("Invalid RAR5 UTF-8 member name");
			}
			cursor.offset += nameSize;
			let linkTarget: string | undefined;
			for (const extra of readExtraRecords(bytes, extraStart, headerEnd)) {
				const extraCursor = { offset: extra.start };
				if (extra.type === 1) throw new ArchiveError(`Encrypted RAR5 member '${rawPath}' is not supported`);
				if (extra.type === 3) {
					const timeFlags = readVint(bytes, extraCursor, extra.end, "time flags");

View on GitHub (pinned to 9690622007)

Solutions

  1. Raise options.limits.maxInMemorySize when the archive is trusted and the dictionary size is acceptable
  2. Re-compress the archive with a smaller dictionary (`rar -md<m>` default is small)
  3. Reject such archives upstream and fall back to the unrar CLI

Example fix

// before
const records = readRar(bytes, { limits: { maxInMemorySize: 64 * 1024 * 1024 } });
// after
const records = readRar(bytes, { limits: { maxInMemorySize: 1024 * 1024 * 1024 } }); // allow 1GiB dictionaries
Defensive patterns

Strategy: validation

Validate before calling

// raise the in-memory cap if trusted archives use big dictionaries
const options = { limits: { maxInMemorySize: 512 * 1024 * 1024 } };

Try / catch

try {
  const records = readRar(bytes, options);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('dictionary is too large')) {
    const m = /\((\d+) bytes\)/.exec(err.message);
    // surface required size to caller, or re-compress externally
  } else throw err;
}

Prevention

When it happens

Trigger: Reading a RAR5 member compressed with a very large dictionary (dictionaryPower near 0x1f, i.e. dictionaries of gigabytes) while options.limits.maxInMemorySize is smaller than that dictionary.

Common situations: Users maximizing compression ratio with `rar -md1g` or larger on huge inputs; archives created with modern WinRAR 7 64-bit dictionary sizes parsed by a library configured with a small memory cap; strict maxInMemorySize set for safety in server environments.

Related errors


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