can1357/oh-my-pi · error · ArchiveError

Unsupported archive format: ${input}

Error message

Unsupported archive format: ${input}

What it means

resolveSource was given a plain string path (no explicit format) and archiveFormatFromPath could not map any known archive extension to a format, so openArchive refuses to proceed. The library only auto-detects format from the file extension for string inputs; anything else must be passed as an object with an explicit format. The error message includes the offending path.

Source

Thrown at packages/utils/src/ar/open.ts:48

	format: ArchiveFormat;
	archivePath?: string;
}

function resolveSource(input: ArchiveSource): ResolvedArchiveSource {
	if (typeof input !== "string") {
		if ("bytes" in input) {
			return { source: memoryByteSource(input.bytes), format: input.format };
		}
		if ("source" in input) {
			return { source: input.source, format: input.format, archivePath: input.path };
		}
		const format = input.format;
		return { source: fileByteSource(input.path), format, archivePath: input.path };
	}

	const format = archiveFormatFromPath(input);
	if (!format) {
		throw new ArchiveError(`Unsupported archive format: ${input}`);
	}
	return { source: fileByteSource(input), format, archivePath: input };
}

/**
 * Open an archive for browsing and member reads. File- and source-backed
 * containers with random-access layouts (ZIP, ASAR, RAR, 7z, ISO, CAB) index
 * lazily; stream containers (tar family, cpio, ar) buffer once under limits.
 */
export async function openArchive(input: ArchiveSource, options: OpenArchiveOptions = {}): Promise<ArchiveReader> {
	const { source, format, archivePath } = resolveSource(input);
	const limits = { ...DEFAULT_ARCHIVE_LIMITS, ...options.limits };
	const readOptions: FormatReadOptions = { limits, archivePath };
	const entries = await formatReaderFor(format)(source, readOptions);
	return new ArchiveReader(format, entries, limits);
}

/**

View on GitHub (pinned to 9690622007)

Solutions

  1. Rename the file to a recognized archive extension (.zip, .tar, .tgz, .7z, .rar, etc.) matching its actual format.
  2. Pass an explicit source object instead of a string: { path, format: "tar" } (or the correct ArchiveFormat).
  3. For in-memory data, use { bytes, format } so no extension is needed.
  4. Check the registry's supported extensions (ARCHIVE_EXTENSION_ALTERNATION in packages/utils/src/ar/registry.ts) and align the input.

Example fix

// before
await openArchive("./data/pack.bin");
// after
await openArchive({ path: "./data/pack.bin", format: "zip" });
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = /\.(zip|tar|tgz|tar\.gz|tar\.bz2|tar\.xz|7z|rar|asar|iso|cab|arj|cpio|ar|lzh)$/i;
if (typeof input === "string" && !KNOWN.test(input)) {
  throw new Error(`Pass an explicit format: openArchive({ path: ${JSON.stringify(input)}, format: "..." })`);
}

Try / catch

try {
  const reader = await openArchive(input);
} catch (err) {
  if (err instanceof ArchiveError && err.message.startsWith("Unsupported archive format:")) {
    // fall back to explicit-format open or inform the user
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling openArchive/extractArchive (or related entry points) with a bare string like 'data.bin', 'backup.old.tar', or an extension the registry does not recognize, instead of { path, format } or { bytes, format }.

Common situations: Passing a file with an unusual or uppercase/misleading extension, a nested-in-archive path without a recognized archive component, or assuming content sniffing is done for plain paths (it is not — only extensions are used).

Related errors


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