can1357/oh-my-pi · error · ArchiveError

Invalid ar archive member name '${reference}'

Error message

Invalid ar archive member name '${reference}'

What it means

resolveLongName handles GNU-style long names stored as '/<offset>' into the string table ('//') member. This throw fires when the text after '/' is not all digits — the member name looks like a long-name reference but the offset is malformed. The library treats this as corruption rather than a literal name, since GNU ar never writes a non-numeric '/...' name.

Source

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

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}'`);
	}
	let end = offset;
	while (end < table.byteLength && table[end] !== 0 && table[end] !== 0x0a) end++;
	if (end === table.byteLength) throw new ArchiveError(`Unterminated ar archive long name at offset ${offset}`);
	let nameEnd = end;
	if (table[end] === 0x0a && nameEnd > offset && table[nameEnd - 1] === 0x2f) nameEnd--;
	if (nameEnd === offset) throw new ArchiveError(`Empty ar archive long name at offset ${offset}`);
	const nameBytes = table.subarray(offset, nameEnd);
	return { name: decodeName(nameBytes, limits), byteLength: nameBytes.byteLength };
}

function isMetadataName(name: string): boolean {
	return name === "/" || name === "//" || name === "/SYM64/" || name === "__.SYMDEF" || name === "__.SYMDEF SORTED";
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Hex-dump the name field (bytes 0-15) of the failing member
  2. Fix the producer to store long names in the '// ' string table and reference them as '/<decimal offset>'
  3. Regenerate the archive with GNU ar or llvm-ar
  4. If a member name legitimately starts with '/', encode it via the long-name table rather than literally

Example fix

// before: literal '/myname' in name field
name = '/myname'
// after: put in string table, reference by offset
nameField = '/' + String(tableOffset).padEnd(15); // e.g. '0              '
Defensive patterns

Strategy: validation

Validate before calling

function nameFieldIsValid(rawName: string): boolean {
  if (rawName === '/' || rawName === '//' || rawName === '/SYM64/') return true;
  if (rawName.startsWith('/')) return /^\/\d+$/.test(rawName);
  return true;
}
// scan member name fields (16-byte slots) before parsing

Type guard

function isLongNameReference(rawName: string): boolean {
  return /^\/\d+$/.test(rawName);
}

Try / catch

try {
  const entries = await archive.list();
} catch (err) {
  if (err instanceof ArchiveError && err.message.startsWith("Invalid ar archive member name '")) {
    // log offending reference from the message; inspect with ar t
  } else throw err;
}

Prevention

When it happens

Trigger: Parsing an archive where a member's rawName is '/xyz', '/12a', '/ 5', or similar non-numeric form; or a '/'-prefixed special name mistyped by a custom writer.

Common situations: Custom archive writers emitting '/name' instead of storing names in the '// ' table; corruption of the 16-byte name field; mixing GNU naming conventions with incompatible tooling.

Related errors


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