can1357/oh-my-pi · error · ArchiveError
Multi-volume ARJ archives are unsupported
Error message
Multi-volume ARJ archives are unsupported
What it means
Bit 2 (0x04) of the ARJ main header flags byte indicates a multi-volume (split across disks/files) archive. The reader parses a single in-memory byte buffer only and cannot follow continuation volumes, so it rejects such archives immediately after reading the main header.
Source
Thrown at packages/utils/src/ar/arj.ts:249
let bytes: Uint8Array;
try {
bytes = await readAllBytes(source);
} catch (error) {
if (error instanceof ArchiveError) throw error;
throw new ArchiveError(`Unable to read ARJ archive: ${error instanceof Error ? error.message : String(error)}`);
}
if (bytes.byteLength !== source.size) throw new ArchiveError("Invalid ARJ archive: truncated data");
if (!sniffArj(bytes)) throw new ArchiveError("Invalid ARJ archive header");
const main = parseArjBlock(bytes, 0, options);
if (main.isEnd) throw new ArchiveError("Invalid ARJ archive: missing main header");
const mainFirstHeaderSize = bytes[main.bodyStart]!;
if (mainFirstHeaderSize < 30 || mainFirstHeaderSize > main.bodySize || bytes[main.bodyStart + 6] !== 2) {
throw new ArchiveError("Invalid ARJ main header");
}
const mainFlags = bytes[main.bodyStart + 4]!;
if ((mainFlags & 0x01) !== 0) throw new ArchiveError("Encrypted ARJ archives are unsupported");
if ((mainFlags & 0x04) !== 0) throw new ArchiveError("Multi-volume ARJ archives are unsupported");
const entries: ArchiveIndexEntry[] = [];
let offset = main.nextOffset;
let metadataSize = main.metadataSize;
let parsedCount = 0;
for (;;) {
const block = parseArjBlock(bytes, offset, options);
metadataSize += block.metadataSize;
assertIndexSize(metadataSize, options.limits, "index");
if (block.isEnd) break;
assertEntryCount(++parsedCount, options.limits);
const firstHeaderSize = bytes[block.bodyStart]!;
if (firstHeaderSize < 30 || firstHeaderSize > block.bodySize) throw new ArchiveError("Invalid ARJ local header");
const hostOs = bytes[block.bodyStart + 3]!;
const flags = bytes[block.bodyStart + 4]!;
const method = bytes[block.bodyStart + 5]!;
const fileType = bytes[block.bodyStart + 6]!;
if ((flags & 0x01) !== 0) throw new ArchiveError("Encrypted ARJ members are unsupported");View on GitHub (pinned to 9690622007)
Solutions
- Rejoin/extract the full volume set with the original ARJ tool or a compatible extractor (e.g. `arj x archive.arj` with all volumes present), then index the resulting single archive or its extracted files.
- Ensure all sibling volumes (.arj, .a01, .a02, ...) are present and, if this library only takes one buffer, pre-merge via an external extractor.
- Detect this case in your pipeline and reject multi-volume inputs explicitly before calling readArj.
- If you create archives, avoid ARJ volume splitting; produce a single archive within your size limits.
Example fix
// before
const entries = await readArj(firstVolumeBytes, options); // throws on multi-volume
// after
if (isMultiVolumeArj(firstVolumeBytes)) {
const merged = await extractVolumesWithArjTool(volumeDir);
const entries = await readArj(merged, options);
} Defensive patterns
Strategy: validation
Validate before calling
function isArjMultiVolume(bytes: Uint8Array): boolean {
const flags = bytes[mainHeaderBodyStart(bytes) + 4] ?? 0;
return (flags & 0x04) !== 0;
}
if (isArjMultiVolume(bytes)) throw new Error("Multi-volume ARJ rejected; rejoin volumes first"); Type guard
function isSingleVolumeArjFlags(flags: number): boolean {
return (flags & 0x04) === 0;
} Try / catch
try {
entries = await readArj(source, options);
} catch (e) {
if (e instanceof ArchiveError && e.message === "Multi-volume ARJ archives are unsupported") {
return { status: "multi-volume", hint: "extract the full volume set with the ARJ tool first" };
}
throw e;
} Prevention
- Check the main header flags (0x04) at ingest time and route multi-volume sets to an external extractor.
- Require all sibling volumes (.a01, .a02, ...) to be present before accepting an upload.
- Prefer single-volume archive formats for new data.
When it happens
Trigger: readArj is called on the first volume of an ARJ multi-volume set (created with ARJ's '-v' volume options); the main header flags byte at bodyStart+4 has 0x04 set.
Common situations: Old floppy-disk-era backups split into .arj/.a01/.a02 files; downloading only the first part of a multi-part archive; archives re-split by transfer size limits.
Related errors
- Multi-volume ARJ members are unsupported
- ARJ member '${memberPath}' uses unsupported compression meth
- Encrypted ARJ archives are unsupported
- Encrypted ARJ members are unsupported
- Unsupported multi-volume CAB archive (previous/next cabinet
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/982907a3ac5ff44c.
Report an issue: GitHub.