can1357/oh-my-pi · error · ArchiveError

Encrypted ZIP member '${rawPath}' is not supported

Error message

Encrypted ZIP member '${rawPath}' is not supported

What it means

Thrown when a ZIP member's central-directory flags indicate encryption (bit 0 ENCRYPTED_FLAG or bit 6 STRONG_ENCRYPTION_FLAG) or the compression method is 99 (AES). The library does not implement decryption, so encrypted members cannot be read.

Source

Thrown at packages/utils/src/ar/zip.ts:503

			{
				compressedSize: compressedRaw,
				uncompressedSize: uncompressedRaw,
				localHeaderOffset: localOffsetRaw,
				diskStart: diskStartRaw,
			},
			{
				compressedSize: compressedRaw === U32_MAX,
				uncompressedSize: uncompressedRaw === U32_MAX,
				localHeaderOffset: localOffsetRaw === U32_MAX,
				diskStart: diskStartRaw === U16_MAX,
			},
		);
		if (values.diskStart !== 0) throw new ArchiveError("Multi-volume ZIP archives are not supported");
		const rawPath =
			extra.unicodePath ?? ((flags & UTF8_FLAG) !== 0 ? UTF8_DECODER : LEGACY_NAME_DECODER).decode(rawName);
		assertArchivePathString(rawPath, "member path", options.limits.maxPathBytes);
		if ((flags & (ENCRYPTED_FLAG | STRONG_ENCRYPTION_FLAG)) !== 0 || method === 99) {
			throw new ArchiveError(`Encrypted ZIP member '${rawPath}' is not supported`);
		}
		const normalizedPath = normalizeArchiveEntryPath(rawPath);
		if (normalizedPath) {
			assertArchiveMemberSize(
				Math.max(values.uncompressedSize, values.compressedSize),
				normalizedPath,
				options.limits,
			);
			const host = versionMadeBy >>> 8;
			const mode = host === UNIX_HOST || host === OSX_HOST ? externalAttributes >>> 16 : undefined;
			const fileType = mode === undefined ? 0 : mode & FILE_TYPE_MASK;
			const isDirectory =
				isArchiveDirectoryName(rawPath) || fileType === DIRECTORY_TYPE || (externalAttributes & 0x10) !== 0;
			const isSymlink = fileType === SYMLINK_TYPE && !isDirectory;
			const localHeaderOffset = values.localHeaderOffset + info.archiveOffset;
			checkedEnd(localHeaderOffset, 30, source.size, `local header for '${normalizedPath}'`);
			const member = new ZipMemberSource(
				source,

View on GitHub (pinned to 9690622007)

Solutions

  1. Get the password and decrypt/extract the archive with an external tool (`unzip -P pass archive.zip` or `7z x -p<pass>`), then read the plain files
  2. Ask the archive creator to provide an unencrypted ZIP
  3. If you control creation, disable encryption when generating the archive
  4. If password-protected input is a requirement, use a library that supports ZIP decryption

Example fix

// before: reading an encrypted zip directly
const entries = await readZip(Bun.file('secret.zip'));
// after: decrypt externally first
await $`7z x -p${password} secret.zip -o./extracted`;
const entries = await readZip(Bun.file('extracted/plain.zip'));
Defensive patterns

Strategy: try-catch

Validate before calling

const flagsView = new DataView(await Bun.file(zipPath).arrayBuffer());
// heuristic: scan local header signatures and check general-purpose flag bit 0
for (let i = 0; i < flagsView.byteLength - 4; i++) {
  if (flagsView.getUint32(i, true) === 0x04034b50 && (flagsView.getUint16(i + 6, true) & 1))
    throw new Error('zip is password-protected');
}

Try / catch

try {
  return await readZip(file);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('Encrypted ZIP member')) {
    throw new Error('Password-protected archive: decrypt externally with the password first', { cause: err });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling the ZIP reader on an archive created with a password (ZipCrypto or AES-256 via WinZip/7-Zip AES), where the member entry carries the encrypted bit or method 99.

Common situations: Receiving a password-protected ZIP from a colleague; CI pipelines fetching encrypted artifacts; backups exported with encryption enabled by default.

Related errors


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