can1357/oh-my-pi · error · ArchiveError
${error.message}
Error message
${error.message} What it means
In ArReader.read, any non-ArchiveError thrown by the underlying source (I/O errors, decode failures, network errors from a remote source) is caught and re-thrown as an ArchiveError whose message is the original error's message. You see '<original message>' with no additional wrapping.
Source
Thrown at packages/utils/src/ar/unix-ar.ts:43
class ArMemberSource implements MemberSource {
readonly #source: ByteSource;
readonly #offset: number;
constructor(source: ByteSource, offset: number) {
this.#source = source;
this.#offset = offset;
}
async read(size: number, memberPath: string): Promise<Uint8Array> {
try {
const bytes = await this.#source.read(this.#offset, this.#offset + size);
if (bytes.byteLength !== size) {
throw new ArchiveError(`Archive member '${memberPath}' is truncated`);
}
return bytes;
} catch (error) {
if (error instanceof ArchiveError) throw error;
throw new ArchiveError(error instanceof Error ? error.message : String(error));
}
}
}
function decodeAsciiField(bytes: Uint8Array, offset: number, length: number): string {
let end = offset + length;
while (end > offset && bytes[end - 1] === 0x20) end--;
let value = "";
for (let index = offset; index < end; index++) {
const byte = bytes[index]!;
if (byte < 0x20 || byte > 0x7e) throw new ArchiveError("Invalid ar archive header field");
value += String.fromCharCode(byte);
}
return value;
}
function parseOptionalNumber(value: string, radix: 8 | 10, field: string): number | undefined {
if (value === "" || value === "-1") return undefined;View on GitHub (pinned to 9690622007)
Solutions
- Inspect error.message (and cause) to identify the underlying I/O failure and fix that condition
- Wrap read() in try-catch and treat ArchiveError as the unified error type
- Re-open or re-acquire the source before retrying
Example fix
// before
const bytes = await reader.read(size, name);
// after
try {
const bytes = await reader.read(size, name);
} catch (err) {
if (err instanceof ArchiveError) {
// original message preserved in err.message
}
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
try {
await fs.stat(archivePath);
} catch (err) {
throw new Error(`Archive source unavailable: ${err instanceof Error ? err.message : err}`);
} Try / catch
try {
const data = await reader.read(size, name);
} catch (err) {
if (err instanceof ArchiveError) {
// original cause is in err.message; log and handle I/O condition
}
throw err;
} Prevention
- Keep source handles/files alive while reading members
- Handle ENOENT/EACCES on the archive path before member reads
- For remote sources, use retry with range-request verification
When it happens
Trigger: The backing source's read() rejects — e.g. ENOENT/EISDIR on a file source, a closed stream, a network abort on an HTTP-range source, or a permissions error during the read.
Common situations: Reading an ar member after the file was deleted or the handle closed; a remote source returning an error body; permissions changes mid-session.
Related errors
- Failed to read ASAR member '${formatArchivePathForError(memb
- ${error instanceof Error ? error.message : String(error)}
- Archive file '${normalizedPath}' has no readable storage
- error instanceof Error ? error.message : String(error)
- Archive member '${memberPath}' is truncated
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c4466706e7d8ef81.
Report an issue: GitHub.