can1357/oh-my-pi · error · ArchiveError

Invalid ARJ method-4 compressed data: history distance is ou

Error message

Invalid ARJ method-4 compressed data: history distance is out of range

What it means

In method 4, a match's distance (positionCode) must reference bytes already emitted: positionCode < outputPosition, and the window is bounded at 26,624. The decoder throws when the distance is out of this range — referencing data that does not exist yet — because copying from it would read uninitialized output.

Source

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

		}
		if (lengthWidth !== 0) lengthCode += reader.read(lengthWidth);
		if (lengthCode === 0) {
			output[outputPosition++] = reader.read(8);
			continue;
		}
		const length = lengthCode + 2;
		if (length > outSize - outputPosition) {
			throw new ArchiveError("Invalid ARJ method-4 compressed data: match exceeds declared size");
		}
		let positionCode = 0;
		let positionWidth = 9;
		for (; positionWidth < 13; positionWidth++) {
			if (reader.read(1) === 0) break;
			positionCode += 2 ** positionWidth;
		}
		positionCode += reader.read(positionWidth);
		if (positionCode >= 26_624 || positionCode >= outputPosition) {
			throw new ArchiveError("Invalid ARJ method-4 compressed data: history distance is out of range");
		}
		let sourcePosition = outputPosition - positionCode - 1;
		for (let index = 0; index < length; index++) output[outputPosition++] = output[sourcePosition++]!;
	}
	reader.assertZeroPadding();
	return output;
}

class ArjMemberSource implements MemberSource {
	readonly #archive: Uint8Array;
	readonly #start: number;
	readonly #packedSize: number;
	readonly #method: number;
	readonly #crc: number;

	constructor(archive: Uint8Array, start: number, packedSize: number, method: number, crc: number) {
		this.#archive = archive;
		this.#start = start;

View on GitHub (pinned to 9690622007)

Solutions

  1. Confirm the packed payload starts at the member's first byte — starting mid-stream leaves early matches with no history and triggers this error.
  2. Test the member externally (`arj t` / 7-Zip); corruption here usually means the whole archive is damaged — restore from backup.
  3. Ensure the decompressor is fed the exact compressedSize bytes for this member only, not a region spanning adjacent members.
  4. If you are writing a method-4 encoder, never emit a match with distance >= bytes already produced; start streams with literal bytes.

Example fix

// before: feeding a mid-file slice into the decompressor
const packed = bytes.subarray(fileOffset + 100, fileOffset + 100 + entry.compressedSize);
// after: feed the member's full packed stream from its start
const packed = bytes.subarray(entry.dataOffset, entry.dataOffset + entry.compressedSize);
const out = decompressArjMethod4(packed, entry.originalSize);
Defensive patterns

Strategy: try-catch

Validate before calling

// Feed the decompressor the member's complete packed stream from its very first byte
if (entry.dataOffset < 0 || entry.dataOffset + entry.compressedSize > bytes.byteLength) {
  throw new Error(`Member ${entry.name}: packed data out of bounds`);
}
const packed = bytes.subarray(entry.dataOffset, entry.dataOffset + entry.compressedSize);

Try / catch

try {
  return decompressArjMethod4(packed, originalSize);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes("history distance is out of range")) {
    throw new Error(`Member ${name}: corrupt back-reference — packed data likely damaged or mis-sliced`);
  }
  throw err;
}

Prevention

When it happens

Trigger: decompressArjMethod4(): decoded positionCode is >= 26,624 or >= outputPosition. Happens with a match declared near the start of the stream (outputPosition too small), corrupted position-code bits, or a stream whose first bytes are not literal bytes as the format requires.

Common situations: Corrupted packed data flipping position bits, a spliced/truncated stream that starts mid-file so early matches point before the buffer, fuzzed archives probing the window bound, or an encoder bug emitting back-references before enough history exists.

Related errors


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