can1357/oh-my-pi · error · ArchiveError

Duplicate or conflicting ASAR member path '${memberPath}'

Error message

Duplicate or conflicting ASAR member path '${memberPath}'

What it means

encodeAsar rejects a member whose full path (after normalization) is already present in the tree, whether as an exact duplicate or as a node of the opposite kind (file vs directory). The library requires every member path to be unique so the JSON header stays unambiguous. The thrown message includes the offending memberPath.

Source

Thrown at packages/utils/src/ar/asar.ts:437

			const memberPath = writerPath(member[0]);
			const parts = memberPath.split("/");
			let directory = root;
			for (let index = 0; index < parts.length - 1; index++) {
				const part = parts[index]!;
				const existing = directory.files[part];
				if (existing && !("files" in existing)) {
					throw new ArchiveError(
						`ASAR member path '${memberPath}' crosses file '${parts.slice(0, index + 1).join("/")}'`,
					);
				}
				if (!existing) {
					directory.files[part] = { files: Object.create(null) as Record<string, AsarNode> };
				}
				directory = directory.files[part] as AsarDirectoryNode;
			}
			const name = parts.at(-1)!;
			if (directory.files[name]) {
				throw new ArchiveError(`Duplicate or conflicting ASAR member path '${memberPath}'`);
			}
			if (!Number.isSafeInteger(member[1].byteLength) || !Number.isSafeInteger(payloadSize + member[1].byteLength)) {
				throw new ArchiveError("ASAR payload is too large to encode safely");
			}
			directory.files[name] = { size: member[1].byteLength, offset: String(payloadSize) };
			payloads.push(member[1]);
			payloadSize += member[1].byteLength;
		}

		const jsonBytes = ASAR_HEADER_ENCODER.encode(JSON.stringify(root));
		const paddedJsonSize = alignAsarPayload(jsonBytes.byteLength);
		const innerPayloadSize = 4 + paddedJsonSize;
		const headerSize = 4 + innerPayloadSize;
		if (jsonBytes.byteLength > 0xffffffff || headerSize > 0xffffffff) {
			throw new ArchiveError("ASAR header is too large to encode");
		}
		const dataOffset = ASAR_PICKLE_PREFIX_SIZE + headerSize;
		const archiveSize = dataOffset + payloadSize;

View on GitHub (pinned to 9690622007)

Solutions

  1. Deduplicate members by normalized path before calling encodeAsar, keeping the last (or intended) entry.
  2. Fix overlapping glob/include patterns so each file is collected exactly once.
  3. If a directory-vs-file conflict is intended, rename one of the paths.
  4. Catch ArchiveError and log the duplicated memberPath to identify which collection step produced the duplicate.

Example fix

// before
const members = [...glob('**/*'), ...glob('*.txt')]; // a.txt collected twice
// after
const byPath = new Map(members);
const unique = [...byPath.entries()]; // last entry wins
Defensive patterns

Strategy: validation

Validate before calling

function dedupeMembers(members) {
  const byPath = new Map();
  for (const m of members) {
    const key = m[0].replace(/\\/g, '/');
    if (byPath.has(key)) throw new Error(`duplicate ASAR member '${key}'`);
    byPath.set(key, m);
  }
  return [...byPath.values()];
}
const unique = dedupeMembers(members);

Try / catch

try {
  const archive = await encodeAsar(members);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('Duplicate or conflicting ASAR member')) {
    console.error(`Duplicate path in member list: ${err.message}`);
    // fall back to a deduped retry
    return encodeAsar(dedupeMembers(members));
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing the same path twice in the members iterable to encodeAsar/encodeArchive/bytes (e.g. ['a.txt', b1] and ['a.txt', b2]), or a path that was already created as a directory by a longer member, e.g. ['a/b', x] followed by ['a', y].

Common situations: Accidentally including a file twice from overlapping glob patterns (e.g. '**/*' plus '*.txt'); concatenating member lists from two archives that share entries; case-insensitive filesystems where 'Readme.md' and 'readme.md' are the same file but produce distinct keys on some platforms.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/dc92763d433fede5. Report an issue: GitHub.