can1357/oh-my-pi · error · ArchiveError
ASAR member '${formatArchivePathForError(memberPath)}' has a
Error message
ASAR member '${formatArchivePathForError(memberPath)}' has an inconsistent size What it means
The packed ASAR member source records the member's size from the archive header. When read(size, memberPath) is called with a requested size that differs from the header-recorded size, the internal offsets and the caller's expectation disagree — the caller would read the wrong byte range — so the reader refuses rather than returning wrong data.
Source
Thrown at packages/utils/src/ar/asar.ts:117
}
}
class PackedAsarMemberSource implements MemberSource {
readonly #source: ByteSource;
readonly #offset: number;
readonly #size: number;
readonly #integrity?: AsarIntegrity;
constructor(source: ByteSource, offset: number, size: number, integrity: AsarIntegrity | undefined) {
this.#source = source;
this.#offset = offset;
this.#size = size;
this.#integrity = integrity;
}
async read(size: number, memberPath: string): Promise<Uint8Array> {
if (size !== this.#size) {
throw new ArchiveError(`ASAR member '${formatArchivePathForError(memberPath)}' has an inconsistent size`);
}
let bytes: Uint8Array;
try {
bytes = await this.#source.read(this.#offset, this.#offset + this.#size);
} catch (error) {
if (error instanceof ArchiveError) throw error;
throw new ArchiveError(
`Failed to read ASAR member '${formatArchivePathForError(memberPath)}': ${describeError(error)}`,
);
}
if (bytes.byteLength !== this.#size) {
throw new ArchiveError(`ASAR member '${formatArchivePathForError(memberPath)}' is truncated`);
}
verifyIntegrity(bytes, this.#integrity, memberPath);
return bytes;
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Regenerate the ASAR with the official asar tool so header sizes and pickles are consistent.
- Audit any custom ASAR-parsing code: the size passed to read must come from the same header entry (offset+size pair), not a separately parsed pickle.
- Validate the archive structurally (header pickle sizes vs. member entries) before reading members and reject inconsistent files early.
- Verify the file is not truncated/corrupted by comparing whole-file size against the header's expected total.
Example fix
// before const bytes = await source.read(someOtherLength, path); // mismatch → throws // after const entry = headerEntryFor(path); const bytes = await source.read(entry.size, path); // always the header-recorded size
Defensive patterns
Strategy: validation
Validate before calling
// Before reading, confirm every member's size pickle and header entry agree.
function assertAsarSizesConsistent(header: AsarHeader): void {
for (const [p, entry] of Object.entries(header.files)) {
if (!Number.isSafeInteger(entry.size) || entry.size < 0 || entry.offset + entry.size > header.totalSize) {
throw new Error(`ASAR header entry for '${p}' has an inconsistent size`);
}
}
} Type guard
function hasConsistentMemberSize(entry: { offset: number; size: number }, totalSize: number): boolean {
return Number.isSafeInteger(entry.size) && entry.size >= 0 && entry.offset + entry.size <= totalSize;
} Try / catch
try {
const bytes = await member.read(size, path);
} catch (e) {
if (e instanceof ArchiveError && e.message.includes("has an inconsistent size")) {
throw new Error(`ASAR header/data out of sync for '${path}'; repack the archive`);
}
throw e;
} Prevention
- Always take member sizes from the parsed ASAR header entry, never from a separately parsed pickle or hardcoded value.
- Repack with the official asar tool rather than hand-editing ASAR bytes.
- Structurally validate header entries (offset+size within file bounds) before reading members.
When it happens
Trigger: read() on a PackedAsarMemberSource with the size argument (derived by the caller from a pickle/header length field) not equal to the member's #size recorded in the ASAR header — inconsistent size pickles or a caller using the wrong length source.
Common situations: Hand-crafted or third-party-written ASAR files where the size pickle and header entry disagree; bugs in code that manually parses the ASAR header and passes the wrong length; corruption of the size fields.
Related errors
- ASAR member path '${memberPath}' crosses file '${parts.slice
- Duplicate or conflicting ASAR member path '${memberPath}'
- Embedded addon size mismatch for ${filename}: expected ${fil
- Invalid ARJ ${field}: missing terminator
- ARJ member '${memberPath}' extracted to an unexpected size
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/bb25002b7f442e59.
Report an issue: GitHub.