can1357/oh-my-pi · error · ArchiveError
Invalid CPIO archive: unsupported or corrupt magic at offset
Error message
Invalid CPIO archive: unsupported or corrupt magic at offset ${offset} What it means
parseHeader recognizes four CPIO header formats: old binary (0xC771/0x71C7), new ASCII '070701', CRC '070702', and portable ASCII '070707'. If the first bytes at the current parse offset match none of these, it throws ArchiveError with the byte offset. This is the format-detection failure: the data is not a supported CPIO header, is corrupt, or parsing has drifted onto a non-header offset.
Source
Thrown at packages/utils/src/ar/cpio.ts:185
}
if (magic === "070707") {
requireRange(bytes, offset, offset + ODC_HEADER_SIZE, "portable ASCII header");
const field6 = (fieldOffset: number, name: string): number =>
parseDigits(bytes, offset + fieldOffset, 6, 8, name);
return {
headerSize: ODC_HEADER_SIZE,
alignment: 1,
devMajor: 0,
devMinor: field6(6, "device"),
inode: field6(12, "inode"),
mode: field6(18, "mode"),
nlink: field6(36, "link count"),
mtime: parseDigits(bytes, offset + 48, 11, 8, "modification time"),
nameSize: field6(59, "name size"),
fileSize: parseDigits(bytes, offset + 65, 11, 8, "file size"),
};
}
throw new ArchiveError(`Invalid CPIO archive: unsupported or corrupt magic at offset ${offset}`);
}
function decodeUtf8(bytes: Uint8Array): string | undefined {
try {
return UTF8_FATAL_DECODER.decode(bytes);
} catch {
return undefined;
}
}
function validateZeroPadding(bytes: Uint8Array, start: number, end: number, what: string): void {
for (let offset = start; offset < end; offset++) {
if (bytes[offset] !== 0) throw new ArchiveError(`Invalid CPIO archive: non-zero ${what} padding`);
}
}
function makeLinkTarget(recordPath: string, targetBytes: Uint8Array, maxPathBytes: number): LinkTarget {
assertArchivePathBytes(targetBytes.byteLength, "link target", maxPathBytes);View on GitHub (pinned to 9690622007)
Solutions
- Verify the input is a CPIO stream: check leading bytes for '070701'/'070702'/'070707' or use sniffCpio
- For RPM files, decompress the payload (rpm2cpio | gunzip/xz) before parsing
- If the error occurs mid-parse, an earlier entry is malformed — regenerate the archive with standard cpio tooling
- Check you are not passing a compressed stream where an uncompressed one is expected
Example fix
// before: feeding a gzip-compressed cpio directly
const entries = await readCpio(source, options);
// after: sniff and decompress first
const head = new Uint8Array(await source.slice(0, 6));
if (!sniffCpio(head)) throw new Error('not a plain CPIO stream; decompress or convert first');
const entries = await readCpio(source, options); Defensive patterns
Strategy: type-guard
Validate before calling
import { sniffCpio } from '<lib>/ar/cpio';
const head = new Uint8Array(await source.slice(0, 6));
if (!sniffCpio(head)) throw new Error(`not a CPIO stream, magic=${Buffer.from(head).toString('ascii')}`); Type guard
function looksLikeCpio(head: Uint8Array): boolean {
const m = Buffer.from(head.subarray(0, 6)).toString('latin1');
return m === '070701' || m === '070702' || m === '070707' ||
(head[0] === 0xc7 && head[1] === 0x71) || (head[0] === 0x71 && head[1] === 0xc7);
} Try / catch
try {
const entries = await readCpio(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('unsupported or corrupt magic')) {
// wrong format: dispatch to tar/ar reader or decompress first
} else throw err;
} Prevention
- Always sniff magic bytes before choosing a format reader
- For RPM files, decompress the cpio payload (rpm2cpio + gunzip/xz) before parsing
- Do not pass tar/ar/gzip streams to the CPIO reader
- Regenerate truncated archives — mid-stream magic errors usually mean a malformed earlier entry
When it happens
Trigger: readCpio/readRpmArchive/entries called on non-CPIO data (tar, ar, raw bytes); the very first bytes are not a CPIO magic; mid-stream drift after a malformed entry caused the offset to land on file data or padding rather than the next header; a supported-but-unusual variant (e.g. '070703') not implemented.
Common situations: Passing an uncompressed file where a cpio stream was expected, or vice versa (RPM payloads are gzip/xz-compressed cpio — must be decompressed first); feeding a TAR file to the CPIO reader; truncated archives whose trailer is missing so the loop runs into trailing garbage.
Related errors
- Invalid ARJ archive header
- Invalid ARJ header signature
- Invalid XZ stream: footer magic mismatch
- Invalid XZ stream: header position or magic is invalid
- CPIO member '${memberPath}' has an inconsistent declared siz
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f444c0bf5a0c91bb.
Report an issue: GitHub.