{"record":{"id":"38024039c19a5ce4","repo":"can1357/oh-my-pi","slug":"invalid-arj-archive-missing-main-header","errorCode":null,"errorMessage":"Invalid ARJ archive: missing main header","messagePattern":"Invalid ARJ archive: missing main header","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/arj.ts","lineNumber":242,"sourceCode":"\n/** Index an ARJ archive and lazily decode stored, static-Huffman, and fast-LZSS members. */\nexport const readArj: FormatReader = async (\n\tsource: ByteSource,\n\toptions: FormatReadOptions,\n): Promise<ArchiveIndexEntry[]> => {\n\tassertInMemorySize(source.size, options.limits);\n\tlet bytes: Uint8Array;\n\ttry {\n\t\tbytes = await readAllBytes(source);\n\t} catch (error) {\n\t\tif (error instanceof ArchiveError) throw error;\n\t\tthrow new ArchiveError(`Unable to read ARJ archive: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n\tif (bytes.byteLength !== source.size) throw new ArchiveError(\"Invalid ARJ archive: truncated data\");\n\tif (!sniffArj(bytes)) throw new ArchiveError(\"Invalid ARJ archive header\");\n\n\tconst main = parseArjBlock(bytes, 0, options);\n\tif (main.isEnd) throw new ArchiveError(\"Invalid ARJ archive: missing main header\");\n\tconst mainFirstHeaderSize = bytes[main.bodyStart]!;\n\tif (mainFirstHeaderSize < 30 || mainFirstHeaderSize > main.bodySize || bytes[main.bodyStart + 6] !== 2) {\n\t\tthrow new ArchiveError(\"Invalid ARJ main header\");\n\t}\n\tconst mainFlags = bytes[main.bodyStart + 4]!;\n\tif ((mainFlags & 0x01) !== 0) throw new ArchiveError(\"Encrypted ARJ archives are unsupported\");\n\tif ((mainFlags & 0x04) !== 0) throw new ArchiveError(\"Multi-volume ARJ archives are unsupported\");\n\n\tconst entries: ArchiveIndexEntry[] = [];\n\tlet offset = main.nextOffset;\n\tlet metadataSize = main.metadataSize;\n\tlet parsedCount = 0;\n\tfor (;;) {\n\t\tconst block = parseArjBlock(bytes, offset, options);\n\t\tmetadataSize += block.metadataSize;\n\t\tassertIndexSize(metadataSize, options.limits, \"index\");\n\t\tif (block.isEnd) break;\n\t\tassertEntryCount(++parsedCount, options.limits);","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/arj.ts#L224-L260","documentation":"This ArchiveError is thrown when the first block parsed from the archive reports isEnd — meaning the parser hit the end-of-archive marker (bodySize 0) immediately, with no main header present. A valid ARJ must start with a main (archive) header before any local file headers.","triggerScenarios":"Calling readArj on data whose very first block after the signature is an end marker — e.g. an empty/headerless archive, or corruption that zeroed the main header size field.","commonSituations":"Zero-length archives created by aborted archiver runs, severely truncated/corrupted files, files that only consist of the two signature bytes plus terminator.","solutions":["The archive has no content headers; obtain a complete archive from the source.","Verify the file against the original byte size/checksum to detect truncation.","Re-create the archive; if the producer intentionally made an empty archive, it is still not readable as a member-bearing ARJ by this reader."],"exampleFix":"// before\nconst entries = await readArj(source, options);\n// after\ntry {\n  const entries = await readArj(source, options);\n  if (entries.length === 0) console.warn('archive contains no members');\n} catch (e) {\n  if (e instanceof ArchiveError && e.message.includes('missing main header')) {\n    throw new Error('archive is empty or its main header is missing; re-acquire the file');\n  }\n  throw e;\n}","handlingStrategy":"validation","validationCode":"if (stat.size < 34) throw new Error(`${path} is too small to be a member-bearing ARJ archive`);","typeGuard":null,"tryCatchPattern":"try {\n  const entries = await readArj(source, options);\n} catch (e) {\n  if (e instanceof ArchiveError && e.message.includes('missing main header')) {\n    throw new Error('archive is empty or its main header is missing; re-acquire it');\n  }\n  throw e;\n}","preventionTips":["Reject archives smaller than the minimum main-header size (~34 bytes) up front","Compare file size against the original source to detect truncation","Treat zero-content archives as invalid input rather than empty results"],"tags":["archive","arj","corruption","header"],"backgroundTag":"invalid-archive-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}