can1357/oh-my-pi · error · ArchiveError
GNU multi-volume tar members are not supported
Error message
GNU multi-volume tar members are not supported
What it means
Thrown when a tar header has GNU type flag 'M', which marks a continuation member from a GNU multi-volume (split) archive. This library indexes single-volume archives only and does not implement splicing member data across volumes, so it rejects the archive explicitly instead of producing a member with missing bytes. The archive itself may be perfectly valid multi-volume tar — it is just out of scope for this parser.
Source
Thrown at packages/utils/src/ar/tar.ts:486
offset += dataBlocks;
continue;
}
if (typeFlag === "N") {
applyOldGnuNameRecords(data, entries, pendingLinks, limits);
offset += dataBlocks;
continue;
}
if (typeFlag === "x" || typeFlag === "X") {
localPax = parsePaxRecords(data, limits);
offset += dataBlocks;
continue;
}
if (typeFlag === "g") {
applyGlobalPax(globalPax, parsePaxRecords(data, limits));
offset += dataBlocks;
continue;
}
if (typeFlag === "M") throw new ArchiveError("GNU multi-volume tar members are not supported");
if (longName !== undefined) name = longName;
if (longLink !== undefined) linkName = longLink;
const paxPath = paxAttribute(globalPax, localPax, "path");
if (paxPath !== undefined) name = paxPath;
const paxLinkPath = paxAttribute(globalPax, localPax, "linkpath");
if (paxLinkPath !== undefined) linkName = paxLinkPath;
const paxSize = paxAttribute(globalPax, localPax, "size");
if (paxSize !== undefined) size = parsePaxSize(paxSize, "member size");
const paxSparseName = paxAttribute(globalPax, localPax, "GNU.sparse.name");
if (paxSparseName !== undefined) name = paxSparseName;
let displaySize = size;
const paxSparseRealSize = paxAttribute(globalPax, localPax, "GNU.sparse.realsize");
if (paxSparseRealSize !== undefined) displaySize = parsePaxSize(paxSparseRealSize, "sparse real size");
const sparse = typeFlag === "S" || paxDeclaresSparse(globalPax, localPax);
if (typeFlag === "S" && buffer[headerOffset + GNU_SPARSE_ISEXTENDED_OFFSET] === 1) {
let extended = true;
while (extended) {View on GitHub (pinned to 9690622007)
Solutions
- Re-create the archive without multi-volume mode: `tar -cf out.tar dir/` (split afterwards with plain file splitting if size-limited).
- Concatenate volumes only works for raw-split files, not true -M archives; use GNU tar to extract fully first (`tar -xMf vol1 -M -f vol2`) and repack as a single tar.
- Use a tar library that supports multi-volume archives for the read side.
- If you control the producer, switch to per-chunk archives (chunk1.tar, chunk2.tar) and parse each independently.
Example fix
// before tar -M -L 1G -F split-script -cf backup.tar data/ // after: single archive, split as plain bytes if needed tar -cf backup.tar data/ split -b 1G backup.tar backup.tar.part-
Defensive patterns
Strategy: fallback
Validate before calling
// peek first volume headers for GNU multi-volume flag 'M' before parsing
function usesMultiVolume(bytes) {
for (let off = 0; off + 512 <= bytes.byteLength; off += 512) {
if (bytes.every.call(bytes.subarray(off, off + 512), (b) => b === 0)) return false;
if (String.fromCharCode(bytes[off + 156]) === 'M') return true;
const size = parseInt(bytes.subarray(off + 124, off + 136).toString().replace(/[^0-7]/g, ''), 8) || 0;
off += Math.ceil(size / 512) * 512; // skip data blocks
}
return false;
} Try / catch
try {
return readTarEntriesFromBuffer(bytes, { limits });
} catch (err) {
if (err instanceof ArchiveError && /multi-volume/.test(err.message)) {
const merged = await mergeMultiVolumeWithGnuTar(volumePaths); // tar -xM then repack
return readTarEntriesFromBuffer(merged, { limits });
}
throw err;
} Prevention
- Create archives without `tar -M`; split plain files afterwards instead.
- When receiving tape-style backups, ask for a single-volume repack upstream.
- Detect GNU multi-volume input early and route it to GNU tar rather than this parser.
- Document multi-volume as unsupported for consumers of your pipeline.
When it happens
Trigger: Calling readTarEntriesFromBuffer/readTar on an archive created with `tar -M -L <size> -F` (multi-volume) or GNU split backups, at the first header belonging to volume 2+.
Common situations: Old GNU backup scripts (level-0 dumps with -M), tapes split across media converted to files, or someone splitting a tar with an OS-aware splitter that emits proper multi-volume headers rather than raw byte cuts.
Related errors
- Multi-volume ARJ archives are unsupported
- Multi-volume ARJ members are unsupported
- Unsupported multi-volume CAB archive (previous/next cabinet
- Multi-volume LZH archives are unsupported
- Unsupported multi-volume RAR4 archive
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/46771fd832746e98.
Report an issue: GitHub.