{"record":{"id":"d1068c02f3c0fb5a","repo":"can1357/oh-my-pi","slug":"failed-to-read-asar-archive-describeerror-error","errorCode":null,"errorMessage":"Failed to read ASAR archive: ${describeError(error)}","messagePattern":"Failed to read ASAR archive: (.+?)","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/asar.ts","lineNumber":368,"sourceCode":"\t\t\tisDirectory: false,\n\t\t\tsize,\n\t\t\tmode,\n\t\t\tstorage: {\n\t\t\t\ttype: \"member\",\n\t\t\t\tsource: new PackedAsarMemberSource(source, memberOffset, size, integrity),\n\t\t\t},\n\t\t});\n\t}\n\treturn entries;\n}\n\n/** Read an Electron ASAR index while keeping packed and unpacked member payloads lazy. */\nexport const readAsar: FormatReader = async (source, options) => {\n\ttry {\n\t\treturn await readAsarIndex(source, options);\n\t} catch (error) {\n\t\tif (error instanceof ArchiveError) throw error;\n\t\tthrow new ArchiveError(`Failed to read ASAR archive: ${describeError(error)}`);\n\t}\n};\n\n/** Whether bytes begin with a structurally plausible Electron ASAR Pickle header. */\nexport function sniffAsar(bytes: Uint8Array): boolean {\n\tif (bytes.byteLength < ASAR_JSON_OFFSET + 1) return false;\n\tconst outerPayload = readUInt32LE(bytes, 0);\n\tconst headerSize = readUInt32LE(bytes, 4);\n\tconst innerPayload = readUInt32LE(bytes, 8);\n\tconst jsonSize = readUInt32LE(bytes, 12);\n\treturn (\n\t\touterPayload === 4 &&\n\t\theaderSize >= ASAR_INNER_PREFIX_SIZE &&\n\t\theaderSize === innerPayload + 4 &&\n\t\tinnerPayload === 4 + alignAsarPayload(jsonSize) &&\n\t\tjsonSize > 0 &&\n\t\tbytes[ASAR_JSON_OFFSET] === 0x7b\n\t);","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/asar.ts#L350-L386","documentation":"A catch-all wrapper around readAsarIndex: any error thrown while parsing the ASAR index that is NOT already an ArchiveError is re-wrapped as `Failed to read ASAR archive: <cause>`. It indicates an unexpected failure during header parsing (JSON handling, byte-source I/O, limits enforcement from underlying layers) rather than a diagnosed ASAR format problem.","triggerScenarios":"The ByteSource.read implementation rejects (disk error, network stream failure); a JSON.parse or TextDecoder throwing outside the guarded spots; a limit-check helper throwing a non-ArchiveError; any runtime exception in the index walker.","commonSituations":"Custom ByteSource implementations that reject with native errors instead of ArchiveError; memory failures on very large headers; bugs in downstream limit helpers.","solutions":["Read the embedded cause after 'Failed to read ASAR archive:' to identify the real failure","If using a custom ByteSource, make it throw ArchiveError (or validate it returns exactly the requested byte ranges)","Verify the .asar file is complete and readable at the byte-source level (size, permissions) before parsing"],"exampleFix":"// before\nconst src = { size: f.size, read: (a,b) => f.slice(a,b) }; // rejects with raw errors\n// after\nconst src = { size: f.size, read: async (a,b) => { try { return new Uint8Array(await f.slice(a,b).arrayBuffer()); } catch (e) { throw new ArchiveError(`read failed: ${e}`); } } };","handlingStrategy":"try-catch","validationCode":"const bytes = await Bun.file(asarPath).slice(0, 16).bytes();\nif (!sniffAsar(bytes)) throw new Error(\"not a valid ASAR archive\");","typeGuard":"const looksLikeAsar = (bytes) => sniffAsar(bytes);","tryCatchPattern":"try { return await readAsar(source, options); } catch (e) { if (e instanceof ArchiveError) { logger.error(\"asar open failed\", { cause: e.message }); } throw e; }","preventionTips":["Validate the file with sniffAsar before parsing","Wrap custom ByteSource errors in ArchiveError so causes stay structured","Check file completeness/size before reading large headers"],"tags":["asar","parse-error","wrapper-error","io"],"backgroundTag":"asar-parse-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}