{"record":{"id":"3da655cb863a6002","repo":"can1357/oh-my-pi","slug":"archive-file-label-is-unpacked-and-requires-a","errorCode":null,"errorMessage":"Archive file '${label}' is unpacked and requires a filesystem-backed ASAR archive","messagePattern":"Archive file '(.+?)' is unpacked and requires a filesystem-backed ASAR archive","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/asar.ts","lineNumber":153,"sourceCode":"\nclass UnpackedAsarMemberSource implements MemberSource {\n\treadonly #filePath?: string;\n\treadonly #size: number;\n\treadonly #integrity?: AsarIntegrity;\n\n\tconstructor(filePath: string | undefined, size: number, integrity: AsarIntegrity | undefined) {\n\t\tthis.#filePath = filePath;\n\t\tthis.#size = size;\n\t\tthis.#integrity = integrity;\n\t}\n\n\tasync read(size: number, memberPath: string): Promise<Uint8Array> {\n\t\tconst label = formatArchivePathForError(memberPath);\n\t\tif (size !== this.#size) {\n\t\t\tthrow new ArchiveError(`ASAR member '${label}' has an inconsistent size`);\n\t\t}\n\t\tif (!this.#filePath) {\n\t\t\tthrow new ArchiveError(`Archive file '${label}' is unpacked and requires a filesystem-backed ASAR archive`);\n\t\t}\n\t\tconst file = Bun.file(this.#filePath);\n\t\tconst stat = await file.stat().catch(() => {\n\t\t\tthrow new ArchiveError(`Unpacked ASAR file '${label}' was not found`);\n\t\t});\n\t\tif (stat.isDirectory()) {\n\t\t\tthrow new ArchiveError(`Unpacked ASAR file '${label}' is a directory`);\n\t\t}\n\t\tif (stat.size !== this.#size) {\n\t\t\tthrow new ArchiveError(\n\t\t\t\t`Unpacked ASAR file '${label}' size differs from its archive header (${stat.size} != ${this.#size} bytes)`,\n\t\t\t);\n\t\t}\n\t\tlet bytes: Uint8Array;\n\t\ttry {\n\t\t\tbytes = await file.bytes();\n\t\t} catch (error) {\n\t\t\tthrow new ArchiveError(`Failed to read unpacked ASAR file '${label}': ${describeError(error)}`);","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/asar.ts#L135-L171","documentation":"Thrown by UnpackedAsarMemberSource.read when an ASAR entry is flagged `unpacked: true` but no filesystem path could be resolved for its sidecar file. Unpacked members live in `<archive>.unpacked/` next to the ASAR file, and their absolute path can only be computed when the archive was opened via `options.archivePath`. Reading such a member from an in-memory or stream-backed source is impossible.","triggerScenarios":"Reading an unpacked member of an ASAR that was opened from a stream or memory buffer (no archivePath), so UnpackedAsarMemberSource was constructed with filePath === undefined.","commonSituations":"Opening a downloaded or bundled .asar from bytes and then reading a member that the packager marked unpacked (common with Electron apps using asar.unpack); embedding ASAR parsing where only raw bytes are available.","solutions":["Open the archive with its real filesystem path so options.archivePath is set and `<asar>.unpacked/` sidecars can be resolved","Ship the `<archive>.unpacked/` directory alongside the .asar file when distributing","Repack the ASAR without unpacked files (no `unpack` options) if only the single .asar will be available"],"exampleFix":"// before\nconst archive = await readArchive(await Bun.file(app.asar).bytes());\n// after\nconst archive = await readArchiveFromFile(\"/app/resources/app.asar\", { archivePath: \"/app/resources/app.asar\" });","handlingStrategy":"fallback","validationCode":"if (entry.storage?.source instanceof UnpackedAsarMemberSource) {\n  // only safe when archive was opened with archivePath\n  if (!options.archivePath) throw new Error(\"unpacked member requires filesystem-backed archive\");\n}","typeGuard":"const canReadUnpacked = (entry) => !isUnpacked(entry) || Boolean(options.archivePath);","tryCatchPattern":"try { return await readMember(entry); } catch (e) { if (String(e.message).includes(\"requires a filesystem-backed ASAR\")) return readUnpackedFromDisk(`${asarPath}.unpacked/${entry.path}`); throw e; }","preventionTips":["Open ASAR archives by file path (with archivePath) whenever unpacked members are expected","Distribute the .unpacked directory together with the .asar","Prefer fully-packed archives when shipping a single file"],"tags":["asar","unpacked-files","filesystem","electron"],"backgroundTag":"asar-unpacked-file-missing","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}