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
- Hex-dump the name field (bytes 0-15) of the failing member
- Fix the producer to store long names in the '// ' string table and reference them as '/<decimal offset>'
- Regenerate the archive with GNU ar or llvm-ar
- 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
- Store long names in the '// ' table; reference as '/<offset>' only
- Never write literal '/name' into the name field
- Keep GNU naming conventions if targeting GNU ar readers
- Add a writer unit test that round-trips a long filename
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
- Invalid ar archive BSD extended name length
- Invalid ar archive long-name offset '${reference}'
- Unterminated ar archive long name at offset ${offset}
- Invalid ar archive ${field}
- Invalid ar archive member size
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fb311a462bc67a3a.
Report an issue: GitHub.