can1357/oh-my-pi · error · ArchiveError

Invalid archive link

Error message

Invalid archive link

What it means

Wraps a non-ArchiveError failure from resolveArchiveLinkPath into a generic ArchiveError("Invalid archive link") during pending-link resolution. It means link-target resolution failed in an unexpected way while settling a tar symlink/hard-link entry.

Source

Thrown at packages/utils/src/ar/tar.ts:362

	const findUnresolvedBlocker = (targetPath: string): ArchiveIndexEntry | null => {
		for (let end = targetPath.length; end > 0; end = targetPath.lastIndexOf("/", end - 1)) {
			const prefixEntry = entries.get(targetPath.slice(0, end));
			if (prefixEntry && unresolved.has(prefixEntry)) return prefixEntry;
		}
		return null;
	};
	const queue = [...unresolved];
	while (queue.length > 0) {
		const entry = queue.pop()!;
		if (!unresolved.has(entry)) continue;
		const pending = pendingLinks.get(entry)!;
		let blocker = findUnresolvedBlocker(pending.targetPath);
		let targetPath = pending.targetPath;
		if (blocker === null) {
			try {
				targetPath = resolveArchiveLinkPath(entries, targetPath, limits.maxLinkDepth);
			} catch (error) {
				if (!(error instanceof ArchiveError)) throw new ArchiveError("Invalid archive link");
			}
			if (targetPath !== pending.targetPath) blocker = findUnresolvedBlocker(targetPath);
		}
		if (blocker !== null && blocker !== entry) {
			const waiting = dependents.get(blocker);
			if (waiting) waiting.push(entry);
			else dependents.set(blocker, [entry]);
			continue;
		}
		unresolved.delete(entry);
		const settled = dependents.get(entry);
		if (settled) {
			dependents.delete(entry);
			queue.push(...settled);
		}
		if (blocker === entry) {
			if (pending.kind === "hard link") {
				throw new ArchiveError(

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the original error by catching ArchiveError and checking message context; enable debug logging to see the failing link.
  2. Examine the archive's link structure (`tar tvf`) for unusually deep symlink chains and re-pack without them.
  3. Report a bug with the offending archive if a normal archive triggers it — non-ArchiveError escapes here suggest a library defect.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await readTar(bytes, opts);
} catch (e) {
  if (e instanceof ArchiveError && e.message === "Invalid archive link") {
    logger.error("tar link resolution failed unexpectedly", { error: e });
    throw new Error("Archive link graph could not be resolved");
  }
  throw e;
}

Prevention

When it happens

Trigger: During resolvePendingLinks, resolveArchiveLinkPath(entries, targetPath, maxLinkDepth) throws something that is not an ArchiveError (e.g. a RangeError from runaway recursion or an internal bug), so the catch block re-wraps it.

Common situations: Pathological archives with deeply nested or self-referential symlink chains that trip the depth limit via an unexpected error type; library-internal edge cases.

Related errors


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