can1357/oh-my-pi · error · ArchiveError

Unsupported compressed RAR4 symlink '${path}'

Error message

Unsupported compressed RAR4 symlink '${path}'

What it means

When a RAR4 member's Unix mode indicates a symlink (S_IFLNK, 0xa000), the parser expects the link target to be stored uncompressed (method 0x30 'store') with packed size equal to unpacked size, since it reads the target as raw bytes from the data area. A symlink stored with any compression method, or with mismatched sizes, cannot be read this way, so it throws ArchiveError naming the member path.

Source

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

					const count = mode & 3;
					need(cursor, count, headerEnd, "RAR4 extended time precision");
					for (let index = 0; index < count; index++) {
						remainder |= bytes[cursor++]! << ((index + 3 - count) * 8);
					}
					preciseMs += remainder / 10000;
					if (timeIndex === 0) mtimeMs = preciseMs;
				}
			}
			assertArchiveMemberSize(unpackedSize, rawPath, options.limits);
			const path = normalizeArchiveEntryPath(rawPath);
			if (path) {
				const directory = ((flags >>> 5) & 7) === 7;
				const mode = hostOs === 3 ? attributes : undefined;
				let linkTarget: string | undefined;
				let linkResolveTarget: boolean | undefined;
				if (mode !== undefined && (mode & 0xf000) === 0xa000) {
					if (methodByte !== 0x30 || packedSize !== unpackedSize)
						throw new ArchiveError(`Unsupported compressed RAR4 symlink '${path}'`);
					assertArchivePathBytes(packedSize, "link target", options.limits.maxPathBytes);
					const canonical = canonicalLinkTarget(path, LATIN1.decode(bytes.subarray(dataStart, dataEnd)));
					linkTarget = canonical.target;
					linkResolveTarget = canonical.resolveTarget;
				}
				records.push({
					format: 4,
					path,
					dataStart,
					packedSize,
					unpackedSize,
					method: methodByte - 0x30,
					version,
					dictionarySize: rar4Dictionary(flags),
					solid: (flags & 0x10) !== 0,
					crc: dataCrc,
					isDirectory: directory,
					mtimeMs,

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-create the archive with WinRAR/rar so symlinks are stored uncompressed (standard behavior), or use -m0/store for the link entries.
  2. Extract externally with unrar and repackage; resolve symlinks to real files or a manifest before archiving.
  3. If you control the pipeline, replace symlinks with regular files (or record targets in a side file) before compression.
  4. Catch ArchiveError per path and skip/handle symlink members via an external extractor.

Example fix

// before: tool compressed symlink payload
$`some-rar a archive.rar tree/` // compressed symlink target
// after
$`rar a -m0 archive.rar tree/` // store, keeps symlink targets raw
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const recs = await records(file);
} catch (err) {
  if (err instanceof ArchiveError && err.message.startsWith("Unsupported compressed RAR4 symlink")) {
    // re-pack with WinRAR/rar or extract externally; the message names the offending path
  } else throw err;
}

Prevention

When it happens

Trigger: Calling records() on a RAR4 archive that contains a symbolic link whose target data was compressed (created by tools/settings that compress symlink payloads instead of storing them).

Common situations: Unix archives of directory trees containing symlinks packed by non-WinRAR tools (e.g. some Linux rar ports) that compress link targets; old tar-to-rar conversions.

Related errors


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