{"record":{"id":"f444c0bf5a0c91bb","repo":"can1357/oh-my-pi","slug":"invalid-cpio-archive-unsupported-or-corrupt-magic","errorCode":null,"errorMessage":"Invalid CPIO archive: unsupported or corrupt magic at offset ${offset}","messagePattern":"Invalid CPIO archive: unsupported or corrupt magic at offset (.+?)","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/cpio.ts","lineNumber":185,"sourceCode":"\t}\n\tif (magic === \"070707\") {\n\t\trequireRange(bytes, offset, offset + ODC_HEADER_SIZE, \"portable ASCII header\");\n\t\tconst field6 = (fieldOffset: number, name: string): number =>\n\t\t\tparseDigits(bytes, offset + fieldOffset, 6, 8, name);\n\t\treturn {\n\t\t\theaderSize: ODC_HEADER_SIZE,\n\t\t\talignment: 1,\n\t\t\tdevMajor: 0,\n\t\t\tdevMinor: field6(6, \"device\"),\n\t\t\tinode: field6(12, \"inode\"),\n\t\t\tmode: field6(18, \"mode\"),\n\t\t\tnlink: field6(36, \"link count\"),\n\t\t\tmtime: parseDigits(bytes, offset + 48, 11, 8, \"modification time\"),\n\t\t\tnameSize: field6(59, \"name size\"),\n\t\t\tfileSize: parseDigits(bytes, offset + 65, 11, 8, \"file size\"),\n\t\t};\n\t}\n\tthrow new ArchiveError(`Invalid CPIO archive: unsupported or corrupt magic at offset ${offset}`);\n}\n\nfunction decodeUtf8(bytes: Uint8Array): string | undefined {\n\ttry {\n\t\treturn UTF8_FATAL_DECODER.decode(bytes);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction validateZeroPadding(bytes: Uint8Array, start: number, end: number, what: string): void {\n\tfor (let offset = start; offset < end; offset++) {\n\t\tif (bytes[offset] !== 0) throw new ArchiveError(`Invalid CPIO archive: non-zero ${what} padding`);\n\t}\n}\n\nfunction makeLinkTarget(recordPath: string, targetBytes: Uint8Array, maxPathBytes: number): LinkTarget {\n\tassertArchivePathBytes(targetBytes.byteLength, \"link target\", maxPathBytes);","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/cpio.ts#L167-L203","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: feeding a gzip-compressed cpio directly\nconst entries = await readCpio(source, options);\n// after: sniff and decompress first\nconst head = new Uint8Array(await source.slice(0, 6));\nif (!sniffCpio(head)) throw new Error('not a plain CPIO stream; decompress or convert first');\nconst entries = await readCpio(source, options);","handlingStrategy":"type-guard","validationCode":"import { sniffCpio } from '<lib>/ar/cpio';\nconst head = new Uint8Array(await source.slice(0, 6));\nif (!sniffCpio(head)) throw new Error(`not a CPIO stream, magic=${Buffer.from(head).toString('ascii')}`);","typeGuard":"function looksLikeCpio(head: Uint8Array): boolean {\n  const m = Buffer.from(head.subarray(0, 6)).toString('latin1');\n  return m === '070701' || m === '070702' || m === '070707' ||\n    (head[0] === 0xc7 && head[1] === 0x71) || (head[0] === 0x71 && head[1] === 0xc7);\n}","tryCatchPattern":"try {\n  const entries = await readCpio(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes('unsupported or corrupt magic')) {\n    // wrong format: dispatch to tar/ar reader or decompress first\n  } else throw err;\n}","preventionTips":["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"],"tags":["archive","cpio","format-detection","magic-bytes"],"backgroundTag":"unsupported-archive-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}