can1357/oh-my-pi · error · ArchiveError
Invalid ARJ basic header CRC32
Error message
Invalid ARJ basic header CRC32
What it means
ARJ basic headers end with a CRC-32 over the header body, stored immediately after it. parseArjBlock computes crc32 over bytes [bodyStart, bodyEnd) and compares it with the little-endian u32 at bodyEnd. A mismatch means the header bytes were altered or misread, so the parser stops rather than trusting corrupted metadata (names, sizes, timestamps).
Source
Thrown at packages/utils/src/ar/arj.ts:74
nextOffset: number;
metadataSize: number;
isEnd: boolean;
}
function parseArjBlock(bytes: Uint8Array, offset: number, options: FormatReadOptions): ArjBlock {
assertRange(bytes, offset, offset + 4, "header signature");
if (bytes[offset] !== ARJ_SIGNATURE_0 || bytes[offset + 1] !== ARJ_SIGNATURE_1) {
throw new ArchiveError("Invalid ARJ header signature");
}
const bodySize = u16(bytes, offset + 2);
if (bodySize === 0)
return { bodyStart: offset + 4, bodySize: 0, nextOffset: offset + 4, metadataSize: 4, isEnd: true };
if (bodySize < 30 || bodySize > ARJ_MAX_BASIC_HEADER) throw new ArchiveError("Invalid ARJ basic header size");
const bodyStart = offset + 4;
const bodyEnd = bodyStart + bodySize;
assertRange(bytes, bodyStart, bodyEnd + 4, "basic header");
if (crc32(bytes.subarray(bodyStart, bodyEnd)) !== u32(bytes, bodyEnd)) {
throw new ArchiveError("Invalid ARJ basic header CRC32");
}
let cursor = bodyEnd + 4;
let extensionCount = 0;
for (;;) {
assertRange(bytes, cursor, cursor + 2, "extended header size");
const extensionSize = u16(bytes, cursor);
cursor += 2;
if (extensionSize === 0) break;
if (++extensionCount > 65_535) throw new ArchiveError("Invalid ARJ archive: too many extended headers");
assertRange(bytes, cursor, cursor + extensionSize + 4, "extended header");
if (crc32(bytes.subarray(cursor, cursor + extensionSize)) !== u32(bytes, cursor + extensionSize)) {
throw new ArchiveError("Invalid ARJ extended header CRC32");
}
cursor += extensionSize + 4;
assertIndexSize(cursor - offset, options.limits, "header metadata");
}
return { bodyStart, bodySize, nextOffset: cursor, metadataSize: cursor - offset, isEnd: false };
}View on GitHub (pinned to 9690622007)
Solutions
- Verify the archive externally (`arj t archive.arj`, 7-Zip test) to confirm corruption, then restore from a known-good copy.
- If the file was transferred, re-transfer in binary mode and compare checksums (sha256sum) between source and destination.
- If you generate ARJ files, ensure you CRC-32 the header body and append it little-endian; test with a reference reader.
- Never hand-edit ARJ header bytes (filenames, flags) without recomputing the stored CRC-32.
Example fix
// before: editing the header body in place without fixing the CRC bytes.set(newNameBytes, nameOffset); // after: rebuild the header, recompute CRC-32, and rewrite both body and CRC bytes.set(newNameBytes, nameOffset); const crc = crc32(bytes.subarray(bodyStart, bodyEnd)); new DataView(bytes.buffer).setUint32(bodyEnd, crc, true);
Defensive patterns
Strategy: try-catch
Try / catch
try {
return readArj(data, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("basic header CRC32")) {
// corrupt header — quarantine the file, do not attempt partial extraction
logger.error("ARJ basic header CRC mismatch", { size: data.byteLength });
return null;
}
throw err;
} Prevention
- Always transfer archives in binary mode; verify checksums end-to-end.
- Never hand-edit header bytes without recomputing the CRC-32.
- Run an external integrity test before processing user-supplied archives.
When it happens
Trigger: Any single-bit or multi-byte change inside the basic header body, or the size field being wrong so bodyStart/bodyEnd are shifted and a different region is hashed. Thrown from parseArjBlock after assertRange passes.
Common situations: Damaged downloads or media errors, an in-place file edit (e.g. someone patched a stored filename by hand), transmission through a channel that altered bytes (FTP ASCII mode on old tooling), or a generator that writes headers without computing the CRC.
Related errors
- Invalid ARJ extended header CRC32
- Invalid ARJ archive: truncated ${what}
- Invalid ARJ ${field}: missing terminator
- Invalid ARJ basic header size
- Invalid ARJ archive: too many extended headers
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8de7e9a9ac4e9c55.
Report an issue: GitHub.