can1357/oh-my-pi · error · ArchiveError

Invalid RAR5 UTF-8 member name

Error message

Invalid RAR5 UTF-8 member name

What it means

The member's file name bytes are decoded as UTF-8 (RAR5 stores names in UTF-8). If the byte range fails UTF-8 validation, the library throws this ArchiveError rather than emitting a record with a corrupted path — usually a sign the file is not a genuine RAR5 archive or is corrupted.

Source

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

			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");
					if ((timeFlags & 2) !== 0) {
						if ((timeFlags & 1) !== 0) {
							need(extraCursor.offset, 4, extra.end, "Unix modification time");
							mtimeMs = readUInt32LE(bytes, extraCursor.offset) * 1000;
						} else {
							need(extraCursor.offset, 8, extra.end, "Windows modification time");
							mtimeMs = filetimeMs(bytes, extraCursor.offset);
						}
					}
				} else if (extra.type === 5) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the archive integrity (`unrar t archive.rar`) and re-download/re-extract if corrupt
  2. Confirm the file is really RAR5 (`file archive.rar`) and not a renamed archive of another format
  3. If it is a genuine corrupted archive, repair with WinRAR's repair function or `rar r`
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const records = readRar(bytes);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('Invalid RAR5 UTF-8')) {
    throw new Error('Archive is corrupt or not a valid RAR5 file');
  } else throw err;
}

Prevention

When it happens

Trigger: Decoding bytes.subarray(name bytes) with UTF8.decode throws — non-UTF-8 name bytes in a file header, corrupt/truncated data misdetected as RAR5, or a forged header with an invalid nameSize pointing at binary data.

Common situations: Corrupted downloads; files with a RAR5-like signature but different inner format; archives damaged in transfer; malicious files crafted to break parsers.

Related errors


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