can1357/oh-my-pi · error · ArchiveError

ASAR member ' ' has an inconsistent size

Error message

ASAR member '${label}' has an inconsistent size

What it means

This ArchiveError is thrown by UnpackedAsarMemberSource.read when the `size` argument passed by the archive framework does not match the member size recorded in the ASAR header. It is an internal consistency check: the caller must request exactly the byte count the index declares for this file. A mismatch means either the caller passed a wrong size or the archive index was built from inconsistent metadata.

Solutions

  1. Ensure the size passed to read() comes from the same ArchiveIndexEntry the MemberSource was created from (entry.size), not a separately computed value
  2. Re-read the archive index so entry metadata and member sources are in sync
  3. Check whether custom code caches entry sizes across re-parses and clear that cache

Example fix

// before
const bytes = await member.read(myEstimatedSize, entry.path);
// after
const bytes = await member.read(entry.size, entry.path);
Defensive patterns

Strategy: validation

Validate before calling

if (requestedSize !== entry.size) throw new Error(`size mismatch for ${entry.path}: ${requestedSize} != ${entry.size}`);
await member.read(entry.size, entry.path);

Type guard

function isEntrySize(entry, size) { return size === entry.size; }

Try / catch

try { bytes = await member.read(entry.size, entry.path); } catch (e) { if (e instanceof ArchiveError && e.message.includes("inconsistent size")) { /* re-read fresh index and retry */ } else throw e; }

Prevention

When it happens

Trigger: Calling read() on an unpacked ASAR member entry with a size argument different from the entry's declared size in the ASAR JSON header (e.g. reading with a stale size after the index was re-parsed, or a framework caller computing size from the wrong entry).

Common situations: Bugs in code that resolves archive entries by path and passes the wrong entry's size; custom tooling that manually reads members instead of going through the archive API; corrupted or hand-edited ASAR headers.

Related errors


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

Appendix: source

Thrown at packages/utils/src/ar/asar.ts:150

		return bytes;
	}
}

class UnpackedAsarMemberSource implements MemberSource {
	readonly #filePath?: string;
	readonly #size: number;
	readonly #integrity?: AsarIntegrity;

	constructor(filePath: string | undefined, size: number, integrity: AsarIntegrity | undefined) {
		this.#filePath = filePath;
		this.#size = size;
		this.#integrity = integrity;
	}

	async read(size: number, memberPath: string): Promise<Uint8Array> {
		const label = formatArchivePathForError(memberPath);
		if (size !== this.#size) {
			throw new ArchiveError(`ASAR member '${label}' has an inconsistent size`);
		}
		if (!this.#filePath) {
			throw new ArchiveError(`Archive file '${label}' is unpacked and requires a filesystem-backed ASAR archive`);
		}
		const file = Bun.file(this.#filePath);
		const stat = await file.stat().catch(() => {
			throw new ArchiveError(`Unpacked ASAR file '${label}' was not found`);
		});
		if (stat.isDirectory()) {
			throw new ArchiveError(`Unpacked ASAR file '${label}' is a directory`);
		}
		if (stat.size !== this.#size) {
			throw new ArchiveError(
				`Unpacked ASAR file '${label}' size differs from its archive header (${stat.size} != ${this.#size} bytes)`,
			);
		}
		let bytes: Uint8Array;
		try {

View on GitHub (pinned to 9690622007)