can1357/oh-my-pi · error · ArchiveError

Invalid ARJ archive: no members

Error message

Invalid ARJ archive: no members

What it means

After walking all ARJ blocks, if zero actual file members were indexed (only the main header and possibly an end-of-archive block were present), the reader considers the archive invalid. An ARJ that carries no member entries cannot yield a usable index, so it is rejected rather than returning an empty list.

Source

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

		let mode: number | undefined;
		if ((hostOs === 2 || hostOs === 8) && accessMode !== 0) {
			mode = (isDirectory ? 0x4000 : 0x8000) | (accessMode & 0x0fff);
		}
		const rawMtime = u32(bytes, block.bodyStart + 8);
		const mtimeMs =
			hostOs === 2 || hostOs === 8 ? (rawMtime === 0 ? undefined : rawMtime * 1000) : dosTimeToMs(rawMtime);
		entries.push({
			path,
			isDirectory,
			size: isDirectory ? 0 : size,
			mtimeMs,
			mode,
			storage: isDirectory
				? undefined
				: { type: "member", source: new ArjMemberSource(bytes, dataStart, packedSize, method, fileCrc) },
		});
	}
	if (parsedCount === 0) throw new ArchiveError("Invalid ARJ archive: no members");
	return entries;
};

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the archive with the original ARJ tool (`arj l archive.arj`) to confirm whether it truly contains files; re-create or re-download it if not.
  2. Check the producer pipeline — an empty archive usually means the file list given to the packer was empty or all inputs failed.
  3. Pre-check the file size/structure (expect more than just a ~30+ byte main header plus end block) before calling readArj and fail with your own clearer message.
  4. If your code should tolerate empty archives, catch ArchiveError and treat it as an empty index after verifying the source is genuinely an ARJ.

Example fix

// before
const entries = await readArj(bytes, options); // throws "no members"
// after
try {
  const entries = await readArj(bytes, options);
} catch (e) {
  if (e instanceof ArchiveError && e.message.includes("no members")) {
    return []; // tolerate intentionally empty archives
  }
  throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

function assertArjHasMembers(bytes: Uint8Array): void {
	// an ARJ with content is always larger than its main header + end-of-archive block
	if (bytes.length < 64) throw new Error("File too small to be a populated ARJ archive");
}

Try / catch

try {
	entries = await readArj(source, options);
} catch (e) {
	if (e instanceof ArchiveError && e.message === "Invalid ARJ archive: no members") {
		logger.warn("ARJ contained zero members", { path });
		return []; // treat as empty if your domain allows it
	}
	throw e;
}

Prevention

When it happens

Trigger: readArj completes its parse loop with parsedCount === 0 — the file had a plausible main header but no local file headers followed (e.g. an empty/truncated archive, a writer bug, or a non-archive file that passed the initial magic/header checks).

Common situations: Zero-byte-content archives produced by a misconfigured packaging job; archives truncated right after the main header; files corrupted or overwritten so only the header remains; fixtures built incorrectly in tests.

Related errors


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