can1357/oh-my-pi · error · ArchiveError
Multi-volume ZIP archives are not supported
Error message
Multi-volume ZIP archives are not supported
What it means
When a ZIP64 locator is present, readZip64Info checks the locator's 'total number of disks' field (offset 4) and the 'which disk the ZIP64 EOCD is on' field (offset 16). Both must be 0/1 for a single-volume archive. Any other value means the archive spans multiple disks/volumes, which this reader does not support.
Source
Thrown at packages/utils/src/ar/zip.ts:136
}
async function readZip64Info(
source: ByteSource,
tail: Uint8Array,
tailStart: number,
eocdOffset: number,
): Promise<CentralDirectoryInfo | undefined> {
const locatorOffset = eocdOffset - ZIP64_LOCATOR_LENGTH;
if (locatorOffset < 0) return undefined;
const locator =
locatorOffset >= tailStart
? tail.subarray(locatorOffset - tailStart, locatorOffset - tailStart + ZIP64_LOCATOR_LENGTH)
: await source.read(locatorOffset, eocdOffset);
if (locator.byteLength !== ZIP64_LOCATOR_LENGTH || readUInt32LE(locator, 0) !== ZIP64_LOCATOR_SIGNATURE) {
return undefined;
}
if (readUInt32LE(locator, 4) !== 0 || readUInt32LE(locator, 16) !== 1) {
throw new ArchiveError("Multi-volume ZIP archives are not supported");
}
const declaredOffset = readUInt64LE(locator, 8);
const candidates = [declaredOffset];
const adjacentOffset = locatorOffset - ZIP64_EOCD_LENGTH;
if (adjacentOffset >= 0 && adjacentOffset !== declaredOffset) candidates.push(adjacentOffset);
for (const candidate of candidates) {
if (candidate < 0 || candidate + ZIP64_EOCD_LENGTH > source.size) continue;
const record = await source.read(candidate, candidate + ZIP64_EOCD_LENGTH);
if (record.byteLength !== ZIP64_EOCD_LENGTH || readUInt32LE(record, 0) !== ZIP64_EOCD_SIGNATURE) continue;
const extensibleSize = readUInt64LE(record, 4);
if (extensibleSize < 44 || candidate + 12 + extensibleSize !== locatorOffset) continue;
if (readUInt32LE(record, 16) !== 0 || readUInt32LE(record, 20) !== 0) {
throw new ArchiveError("Multi-volume ZIP archives are not supported");
}
const entriesOnDisk = readUInt64LE(record, 24);
const entries = readUInt64LE(record, 32);
if (entriesOnDisk !== entries) throw new ArchiveError("Multi-volume ZIP archives are not supported");View on GitHub (pinned to 9690622007)
Solutions
- Reassemble/re-extract the split archive with the original tool, then feed the single reassembled .zip to the reader
- Re-create the archive as a single-volume ZIP (`zip -r out.zip dir`, avoid `-s` split options)
- If your writer emits ZIP64, ensure locator disk fields are zeroed
Example fix
// before
$`7z a -v100m out.zip bigdir`; // spanned volumes -> readZip throws
// after
$`7z a out.zip bigdir`; // single-volume archive
const zip = await readZip(await Bun.file("out.zip").bytes()); Defensive patterns
Strategy: validation
Validate before calling
// Detect a ZIP64 locator early and reject multi-disk archives before parsing
function isSpannedZip64(bytes: Uint8Array): boolean {
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
for (let i = bytes.length - 20; i >= 0 && i > bytes.length - 22 - 20 - 65535; i--) {
if (dv.getUint32(i, true) !== 0x07064b50) continue; // zip64 locator sig
return dv.getUint32(i + 4, true) !== 0 || dv.getUint32(i + 16, true) !== 1;
}
return false;
}
if (isSpannedZip64(bytes)) throw new Error("multi-volume zip: reassemble before parsing"); Try / catch
try {
const zip = await readZip(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("Multi-volume")) {
return instructUserToRejoin("this zip is split across volumes; rejoin with the original tool");
}
throw err;
} Prevention
- Don't create spanned archives (-s / -v split options); use single-file zips for programmatic parsing
- If receiving spanned sets, rejoin them with the original archiving tool before parsing
- Document the single-volume limitation where archives enter your system
When it happens
Trigger: readZip on a ZIP64 archive whose locator declares a non-zero disk count or points the ZIP64 EOCD at a disk other than the last — i.e. a genuinely multi-volume (split) ZIP64 archive.
Common situations: ZIP archives split across multiple files/disks by tools like 7-Zip or WinZip spanned-backup mode; ZIP64 files produced by unusual writers that leave disk fields set to non-zero values.
Related errors
- Unsupported multi-volume CAB archive: split CFDATA block
- Invalid ZIP archive: missing ZIP64 end of central directory
- Invalid ZIP archive: missing ZIP64 central-directory metadat
- Invalid ZIP archive: missing ZIP64 extra field
- Invalid ZIP archive: malformed ZIP64 extra field
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6735329a7ee3baeb.
Report an issue: GitHub.