can1357/oh-my-pi · error · ArchiveError

ARJ member '${memberPath}' failed CRC32 verification

Error message

ARJ member '${memberPath}' failed CRC32 verification

What it means

This ArchiveError is thrown when the CRC32 of the decompressed member data does not match the CRC stored in the member's local header. Method-8 members are exempt (no data). This is the library's end-to-end integrity check: the bytes decoded successfully but are not the bytes that were archived.

Source

Thrown at packages/utils/src/ar/arj.ts:203

				output = decompressLhStatic(packed, size, 26_624, 5, 17, `ARJ method ${this.#method}`);
				break;
			case 4:
				output = decompressArjMethod4(packed, size);
				break;
			case 8:
			case 9:
				if (size !== 0 || packed.byteLength !== 0) {
					throw new ArchiveError(`ARJ member '${memberPath}' has invalid no-data method sizes`);
				}
				output = new Uint8Array(0);
				break;
			default:
				throw new ArchiveError(`ARJ member '${memberPath}' uses unsupported compression method ${this.#method}`);
		}
		if (output.byteLength !== size)
			throw new ArchiveError(`ARJ member '${memberPath}' extracted to an unexpected size`);
		if (this.#method !== 8 && crc32(output) !== this.#crc) {
			throw new ArchiveError(`ARJ member '${memberPath}' failed CRC32 verification`);
		}
		return output;
	}
}

function normalizeHostPath(rawPath: string, hostOs: number): string {
	let path = rawPath.replaceAll("\\", "/");
	if (hostOs === 1) path = path.replaceAll(">", "/");
	else if (hostOs === 4) path = path.replaceAll(":", "/");
	return path;
}

/** Probe whether bytes begin with a CRC-framed ARJ main header. */
export function sniffArj(bytes: Uint8Array): boolean {
	if (bytes.byteLength < 34 || bytes[0] !== ARJ_SIGNATURE_0 || bytes[1] !== ARJ_SIGNATURE_1) return false;
	const size = u16(bytes, 2);
	if (size < 30 || size > ARJ_MAX_BASIC_HEADER || bytes.byteLength < size + 8) return false;
	const body = bytes.subarray(4, 4 + size);

View on GitHub (pinned to 9690622007)

Solutions

  1. Obtain a fresh copy of the archive — CRC failure almost always means the data is damaged.
  2. Verify with the official arj tool (arj t) to confirm which members are bad.
  3. If only one member fails, extract other members and re-acquire the damaged file from its original source.
  4. Re-create the archive from known-good source files.
  5. If failures are reproducible across machines on the same archive, suspect the producing tool rather than your hardware.

Example fix

// before
const data = await member.read(member.size, member.path);
process(data);
// after
try {
  const data = await member.read(member.size, member.path);
  process(data);
} catch (e) {
  if (e instanceof ArchiveError && e.message.includes('CRC32')) {
    throw new Error(`member ${member.path} is corrupt (CRC mismatch); re-download the archive`);
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const data = await member.read(size, path);
} catch (e) {
  if (e instanceof ArchiveError && e.message.includes('CRC32')) {
    throw new Error(`member ${path} failed integrity check; re-download the archive`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling member.read(size, memberPath) on any member with data (methods 0–4) where crc32(output) !== the header CRC — i.e. corrupted stored data or a faulty/buggy decompression path.

Common situations: Silent disk corruption, incomplete downloads, transmission errors, archives modified after creation, or hardware faults (bad RAM) flipping bits during decompression.

Related errors


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