pxb1988/dex2jar · error · ZipException

File too short to be a zip file:

Error message

File too short to be a zip file: 

What it means

ZipFile.readCentralDir (constructor) throws ZipException when the file is smaller than the 22-byte End Of Central Directory record (raf.limit() - ENDHDR < 0), meaning it cannot possibly be a zip archive.

Solutions

  1. Check file length >= 22 bytes before constructing ZipFile
  2. Re-download or regenerate the zip file
  3. Verify the path points to the real archive, not a stub or directory

Example fix

// before
ZipFile zip = new ZipFile(f);
// after
if (f.length() < 22) throw new IOException("not a zip: too small " + f);
ZipFile zip = new ZipFile(f);
Defensive patterns

Strategy: validation

Validate before calling

File f = new File(path);
if (!f.isFile() || f.length() < 22) throw new IOException("too small to be a zip: " + f);

Type guard

boolean isPlausibleZip(File f) { return f.isFile() && f.length() >= 22; }

Try / catch

try { ZipFile z = new ZipFile(f); } catch (ZipException e) { throw new IOException("not a valid zip: " + f, e); }

Prevention

When it happens

Trigger: Opening an empty file, a partially downloaded zip, a truncated DEX-in-zip, or pointing ZipFile at a non-zip file shorter than 22 bytes.

Common situations: Failed/interrupted downloads, placeholder files created but never written, mounting the wrong path in build pipelines.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08). Data as JSON: /api/errors/917597a970848cb3. Report an issue: GitHub.

Appendix: source

Thrown at dex-reader/src/main/java/com/googlecode/d2j/util/zip/ZipFile.java:193

     * 
     * <p>
     * The central directory can be followed by a variable-length comment field, so we have to scan through it
     * backwards. The comment is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff itself, plus
     * apparently sometimes people throw random junk on the end just for the fun of it.
     * 
     * <p>
     * This is all a little wobbly. If the wrong value ends up in the EOCD area, we're hosed. This appears to be the way
     * that everybody handles it though, so we're in good company if this fails.
     */
    private void readCentralDir() throws IOException {
        ByteBuffer raf = this.raf;
        // Scan back, looking for the End Of Central Directory field. If the zip file doesn't
        // have an overall comment (unrelated to any per-entry comments), we'll hit the EOCD
        // on the first try.
        // No need to synchronize raf here -- we only do this when we first open the zip file.
        long scanOffset = raf.limit() - ENDHDR;
        if (scanOffset < 0) {
            throw new ZipException("File too short to be a zip file: " + raf.limit());
        }

        // not check Magic
        // raf.position(0);
        // final int headerMagic = raf.getInt();
        // if (headerMagic != LOCSIG) {
        // throw new ZipException("Not a zip archive");
        // }

        long stopOffset = scanOffset - 65536;
        if (stopOffset < 0) {
            stopOffset = 0;
        }

        while (true) {
            raf.position((int) scanOffset);
            if (raf.getInt() == ENDSIG) {
                break;

View on GitHub (pinned to b5bda4fb49)