skylot/jadx · error · IOException

Failed to open zip: {}, error: {}

Error message

Failed to open zip: {}, error: {}

What it means

The top-level failure when the custom JadxZipParser cannot build a ZipContent and the caller has opted out of the fallback parser via ZipReaderFlags.DONT_USE_FALLBACK. Without that flag jadx would log a warning and silently switch to the fallback parser; with the flag, the original exception is wrapped into an IOException that includes the zip path and the root message. The original cause is chained.

Source

Thrown at jadx-commons/jadx-zip/src/main/java/jadx/zip/parser/JadxZipParser.java:86

	@Override
	public ZipContent open() throws IOException {
		load();
		try {
			int maxEntriesCount = zipSecurity.getMaxEntriesCount();
			if (maxEntriesCount == -1) {
				maxEntriesCount = Integer.MAX_VALUE;
			}
			List<IZipEntry> entries;
			if (flags.contains(ZipReaderFlags.IGNORE_CENTRAL_DIR_ENTRIES)) {
				entries = searchLocalFileHeaders(maxEntriesCount);
			} else {
				entries = loadFromCentralDirs(maxEntriesCount);
			}
			return new ZipContent(this, entries);
		} catch (Exception e) {
			if (flags.contains(ZipReaderFlags.DONT_USE_FALLBACK)) {
				throw new IOException("Failed to open zip: " + zipFile + ", error: " + e.getMessage(), e);
			}
			LOG.warn("Zip open failed, switching to fallback parser, zip: {}", zipFile, e);
			return initFallbackParser();
		}
	}

	public boolean canOpen() {
		try {
			load();
			int eocdStart = searchEndOfCDStart();
			ByteBuffer buf = getBuffer();
			buf.position(eocdStart + 4);
			int diskNum = readU2(buf);
			if (diskNum != 0xFFFF) { // Zip64 not supported
				return true;
			}
		} catch (Exception e) {
			LOG.warn("Jadx parser can't open zip file: {}", zipFile, e);

View on GitHub (pinned to e738a26571)

Solutions

  1. Remove ZipReaderFlags.DONT_USE_FALLBACK from the options so jadx can retry with the fallback parser (default behavior).
  2. Inspect getCause() to find the structural reason (missing EOCD, IO error, etc.).
  3. Confirm the file is actually a zip/APK and not truncated or zero-byte.
  4. If strict parsing is required, pre-validate the file with a CRC/structure check before handing it to jadx.

Example fix

// before
ZipReaderOptions opts = new ZipReaderOptions(security, EnumSet.of(ZipReaderFlags.DONT_USE_FALLBACK));
ZipContent content = new JadxZipParser(file, opts).open();

// after
ZipReaderOptions opts = new ZipReaderOptions(security, ZipReaderFlags.none());
ZipContent content = new JadxZipParser(file, opts).open();
Defensive patterns

Strategy: validation

Validate before calling

// Validate the file is a plausible zip and below parser limits before opening.
import java.util.zip.ZipFile;
if (!file.isFile() || file.length() == 0) {
    throw new IOException("Not a readable zip: " + file);
}
// Confirm magic bytes 'PK'
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
    int sig = raf.readInt();
    if ((sig & 0xFFFF) != 0x4B50) { // 'PK'
        throw new IOException("Not a zip file (bad magic): " + file);
    }
}

Try / catch

try {
    ZipContent content = parser.open();
} catch (IOException e) {
    // message: "Failed to open zip: <file>, error: <reason>"
    LOG.error("Custom parser (no fallback) could not open zip: {}", e.getMessage());
    // optionally retry WITHOUT DONT_USE_FALLBACK
}

Prevention

When it happens

Trigger: Opening a zip through JadxZipParser.load()/open() with a ZipReaderOptions whose flags contain DONT_USE_FALLBACK, when either loadFromCentralDirs() or searchLocalFileHeaders() throws (missing EOCD, bad central directory, IO error, max-entries exceeded).

Common situations: A CI job or programmatic jadx invocation that disables the fallback for reproducibility/strictness, run against a malformed or non-zip file; an archive whose end-of-central-directory record is absent or corrupted; a file that is not actually a zip despite its extension.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/b24cc989fc1c4f1a. Report an issue: GitHub.