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

  1. Inspect error.message (and cause) to identify the underlying I/O failure and fix that condition
  2. Wrap read() in try-catch and treat ArchiveError as the unified error type
  3. 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

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


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