can1357/oh-my-pi · error · ArchiveError

Invalid ar archive empty BSD extended name

Error message

Invalid ar archive empty BSD extended name

What it means

decodeBsdName extracts the BSD extended name from the member data up to the first NUL byte and throws if the resulting name is empty (byte length 0) — i.e. the name region starts with a NUL or has no bytes. Zero-length names are rejected earlier via the '#1/0' range check, so this fires when stored name data is empty despite a claimed positive length.

Source

Thrown at packages/utils/src/ar/unix-ar.ts:115

		const encodedLength = rawName.slice(3);
		if (!/^\d+$/.test(encodedLength)) throw new ArchiveError("Invalid ar archive BSD extended name length");
		bsdNameLength = Number.parseInt(encodedLength, 10);
		if (!Number.isSafeInteger(bsdNameLength) || bsdNameLength <= 0 || bsdNameLength > physicalSize) {
			throw new ArchiveError("Invalid ar archive BSD extended name length");
		}
	}
	return { rawName, physicalSize, mtimeSeconds, mode, bsdNameLength };
}

function decodeName(bytes: Uint8Array, limits: ArchiveLimits): string {
	assertArchivePathBytes(bytes.byteLength, "member path", limits.maxPathBytes);
	return UTF8_DECODER.decode(bytes);
}

function decodeBsdName(bytes: Uint8Array, limits: ArchiveLimits): { name: string; byteLength: number } {
	const nul = bytes.indexOf(0);
	const nameBytes = nul >= 0 ? bytes.subarray(0, nul) : bytes;
	if (nameBytes.byteLength === 0) throw new ArchiveError("Invalid ar archive empty BSD extended name");
	return { name: decodeName(nameBytes, limits), byteLength: nameBytes.byteLength };
}

function shortName(rawName: string): string {
	if (rawName === "/" || rawName === "//" || rawName === "/SYM64/") return rawName;
	return rawName.endsWith("/") ? rawName.slice(0, -1) : rawName;
}

function resolveLongName(
	reference: string,
	table: Uint8Array,
	limits: ArchiveLimits,
): { name: string; byteLength: number } {
	const offsetText = reference.slice(1);
	if (!/^\d+$/.test(offsetText)) throw new ArchiveError(`Invalid ar archive member name '${reference}'`);
	const offset = Number.parseInt(offsetText, 10);
	if (!Number.isSafeInteger(offset) || offset < 0 || offset >= table.byteLength) {
		throw new ArchiveError(`Invalid ar archive long-name offset '${reference}'`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the producer writes the name bytes (length includes name plus NUL padding to even size) immediately at the start of member data
  2. Hex-dump the first bytes of the member data; the filename should appear right after the header
  3. Regenerate with BSD ar / llvm-ar
  4. Use plain ASCII member names if the producer mishandles multibyte names

Example fix

// before: length declared, name bytes missing
memberData = new Uint8Array(4); // padding only
// after: name + NUL, padded to even
const raw = Buffer.concat([Buffer.from(name), Buffer.alloc(1)]);
const data = raw.byteLength % 2 ? Buffer.concat([raw, Buffer.alloc(1)]) : raw;
Defensive patterns

Strategy: validation

Validate before calling

function bsdNameDataPresent(memberData: Uint8Array): boolean {
  const nul = memberData.indexOf(0);
  const nameBytes = nul >= 0 ? memberData.subarray(0, nul) : memberData;
  return nameBytes.byteLength > 0;
}
// check on raw member bytes before handing to the parser

Type guard

function hasNonEmptyName(data: Uint8Array): boolean {
  return data.byteLength > 0 && data[0] !== 0;
}

Try / catch

try {
  await archive.extract(dest);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('empty BSD extended name')) {
    // member data starts with NUL — regenerate archive with BSD ar
  } else throw err;
}

Prevention

When it happens

Trigger: Parsing a BSD '#1/<len>' member whose data begins with 0x00, or whose length refers only to padding bytes, reached through the header decode path during listing/extraction.

Common situations: Custom BSD-style writers that declare a length but forget to write the name bytes; archives where UTF-8 name bytes were stripped; corruption zeroing the head of the member data.

Related errors


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