can1357/oh-my-pi · error · ArchiveError

ARJ member '${memberPath}' has inconsistent stored size

Error message

ARJ member '${memberPath}' has inconsistent stored size

What it means

This ArchiveError is thrown when an ARJ member declares compression method 0 (stored/uncompressed) but its packed byte range in the archive does not match the declared uncompressed size. The library validates that a stored member is a verbatim copy, so a mismatch means the archive's local header is corrupt or the member's packed/size fields disagree.

Source

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

	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;
		this.#packedSize = packedSize;
		this.#method = method;
		this.#crc = crc;
	}

	async read(size: number, memberPath: string): Promise<Uint8Array> {
		const packed = this.#archive.subarray(this.#start, this.#start + this.#packedSize);
		let output: Uint8Array;
		switch (this.#method) {
			case 0:
				if (packed.byteLength !== size)
					throw new ArchiveError(`ARJ member '${memberPath}' has inconsistent stored size`);
				output = packed.slice();
				break;
			case 1:
			case 2:
			case 3:
				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:

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the archive integrity (run arj t or re-download the archive) — the header size fields disagree.
  2. Recreate the archive with a standards-compliant ARJ tool.
  3. Catch ArchiveError and surface the specific memberPath to identify the offending member.
  4. If the source is trusted, compare the member's packedSize and size header fields to confirm they match for method-0 members.

Example fix

// before: blindly reading every member
for (const entry of entries) await entry.read(entry.size, entry.path);
// after: skip/guard stored members with mismatched sizes
for (const entry of entries) {
  try {
    await entry.read(entry.size, entry.path);
  } catch (e) {
    if (e instanceof ArchiveError && e.message.includes('inconsistent stored size')) {
      console.warn(`skipping corrupt stored member: ${entry.path}`);
      continue;
    }
    throw e;
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if (member.packedSize !== member.size) {
  throw new Error(`stored member ${member.path} has mismatched packed/unpacked sizes; archive likely corrupt`);
}
await member.read(member.size, member.path);

Type guard

function isStoredMember(m: { method: number }): boolean {
  return m.method === 0;
}

Try / catch

try {
  const data = await member.read(size, path);
} catch (e) {
  if (e instanceof ArchiveError && e.message.includes('inconsistent stored size')) {
    // skip or report corrupt member
  } else throw e;
}

Prevention

When it happens

Trigger: Calling member.read(size, memberPath) (directly or via archive listing/extraction flows like readArj-driven decompression) on a stored (method 0) ARJ member whose packedSize from the local header differs from the size passed in.

Common situations: Corrupted or truncated archives, archives produced by non-conforming ARJ writers, files edited or patched in place, or archives assembled by concatenation where member headers were not updated.

Related errors


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