{"record":{"id":"6defa2701e0b7f1b","repo":"can1357/oh-my-pi","slug":"invalid-rar-archive-signature-not-found","errorCode":null,"errorMessage":"Invalid RAR archive: signature not found","messagePattern":"Invalid RAR archive: signature not found","errorType":"validation","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rar.ts","lineNumber":207,"sourceCode":"async function indexRarMetadata(\n\tsource: ByteSource,\n\toptions: FormatReadOptions,\n): Promise<{ marker: { version: 4 | 5; offset: number }; segments: SparseSegment[] }> {\n\tlet probeEnd = Math.min(source.size, RAR5_MARKER.byteLength);\n\tlet probe = await source.read(0, probeEnd);\n\tlet marker = findMarker(probe);\n\twhile (!marker && probeEnd < Math.min(source.size, 1024 * 1024 + RAR5_MARKER.byteLength)) {\n\t\tconst nextEnd = Math.min(source.size, 1024 * 1024 + RAR5_MARKER.byteLength, Math.max(64 * 1024, probeEnd * 2));\n\t\tassertIndexSize(nextEnd, options.limits, \"RAR signature scan\");\n\t\tconst next = await source.read(probeEnd, nextEnd);\n\t\tconst combined = new Uint8Array(nextEnd);\n\t\tcombined.set(probe);\n\t\tcombined.set(next, probeEnd);\n\t\tprobe = combined;\n\t\tprobeEnd = nextEnd;\n\t\tmarker = findMarker(probe);\n\t}\n\tif (!marker) throw new ArchiveError(\"Invalid RAR archive: signature not found\");\n\tconst segments: SparseSegment[] = [{ start: 0, bytes: probe }];\n\tlet metadataSize = probe.byteLength;\n\tassertIndexSize(metadataSize, options.limits, \"RAR metadata\");\n\tlet offset = marker.offset + (marker.version === 5 ? RAR5_MARKER.byteLength : RAR4_MARKER.byteLength);\n\twhile (offset < source.size) {\n\t\tif (marker.version === 5) {\n\t\t\tif (offset + 5 > source.size) corrupt(\"truncated RAR5 header\");\n\t\t\tconst prefix = await source.read(offset, Math.min(source.size, offset + 16));\n\t\t\tconst sizeCursor = { offset: 4 };\n\t\t\tconst headerSize = readVint(prefix, sizeCursor, prefix.byteLength, \"header size\");\n\t\t\tif (headerSize > 2 * 1024 * 1024) corrupt(\"RAR5 header exceeds format limit\");\n\t\t\tconst headerEnd = checkedEnd(offset, sizeCursor.offset + headerSize, source.size, \"RAR5 header\");\n\t\t\tassertIndexSize(metadataSize + headerEnd - offset, options.limits, \"RAR metadata\");\n\t\t\tconst header = await source.read(offset, headerEnd);\n\t\t\tsegments.push({ start: offset, bytes: header });\n\t\t\tmetadataSize += header.byteLength;\n\t\t\tassertIndexSize(metadataSize, options.limits, \"RAR metadata\");\n\t\t\tconst cursor = { offset: sizeCursor.offset };","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rar.ts#L189-L225","documentation":"indexRarMetadata() scans the head of the stream for the RAR signature ('Rar!' + 0x1a + version bytes, RAR4 or RAR5). If neither marker is found within the probed bytes, the file is not a recognizable RAR archive and this ArchiveError is thrown.","triggerScenarios":"Calling readRar on a file that is not RAR (zip/7z/tar renamed to .rar), an empty file, a text-mode-mangled download, or a RAR file whose first bytes were stripped.","commonSituations":"Mislabeled downloads from the web; SFTP/FTP ASCII transfers corrupting binary data; truncated files smaller than the marker; opening volume part .r00 instead of .part1.rar.","solutions":["Confirm the file starts with 'Rar!' (hexdump the first 8 bytes) — if not, obtain the correct file","Re-download in binary mode; avoid ASCII/text transfer modes","For multi-part sets, open the first volume (.part1.rar / .rar), not a later part"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const head = new Uint8Array(await file.slice(0, 7).arrayBuffer());\nif (!(head[0]===0x52 && head[1]===0x61 && head[2]===0x72 && head[3]===0x21 && head[4]===0x1a)) {\n  throw new Error('File does not start with the RAR signature');\n}","typeGuard":"function looksLikeRar(head: Uint8Array): boolean {\n  return head.length >= 7 && head[0]===0x52 && head[1]===0x61 && head[2]===0x72 && head[3]===0x21 && head[4]===0x1a;\n}","tryCatchPattern":"try {\n  const reader = await readRar(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError && /signature not found/.test(err.message)) {\n    // sniff actual format (zip/7z/tar) and route to the right reader\n  }\n  throw err;\n}","preventionTips":["Check the 'Rar!' magic before calling readRar; sniff the real format for mislabeled files","Always transfer binaries in binary mode (never ASCII FTP/SFTP modes)","Open multi-volume sets at the first volume (.part1.rar), never later parts","Reject zero-byte or suspiciously small files before parsing"],"tags":["rar","archive","signature","not-a-rar","format-detection"],"backgroundTag":"archive-signature-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}