prestodb/presto · critical · PrestoException

DRUID_SEGMENT_LOAD_ERROR

DRUID_SEGMENT_LOAD_ERROR

Error message

Malformed End of Central Directory Record; does not start with %08x

What it means

Zip64EndOfCentralDirectory.read validates the ZIP64 EOCD locator target starts with the ZIP64 EOCD signature 0x06064b50. When the bytes at the given offset are not that signature, the ZIP64 end-of-central-directory structure is missing or corrupt and DRUID_SEGMENT_LOAD_ERROR is thrown.

Source

Thrown at presto-druid/src/main/java/com/facebook/presto/druid/zip/Zip64EndOfCentralDirectory.java:48

    static final int CD_OFFSET_OFFSET = 48;

    private Zip64EndOfCentralDirectory()
    {
    }

    /**
     * Read the Zip64 end of central directory record from the input stream and parse additional
     * {@link ZipFileData} from it.
     */
    public static void read(ZipFileData file, DataInputSource dataInputSource, long offset)
            throws IOException
    {
        checkArgument(file != null, "Zip file data for source:%s is null", dataInputSource.getId());

        byte[] fixedSizeData = new byte[FIXED_DATA_SIZE];
        dataInputSource.readFully(offset, fixedSizeData);
        if (!ZipUtil.arrayStartsWith(fixedSizeData, ZipUtil.intToLittleEndian(SIGNATURE))) {
            throw new PrestoException(DRUID_SEGMENT_LOAD_ERROR, format("Malformed End of Central Directory Record; does not start with %08x", SIGNATURE));
        }
        file.setZip64(true);
        file.setCentralDirectoryOffset(ZipUtil.getUnsignedLong(fixedSizeData, CD_OFFSET_OFFSET));
        file.setExpectedEntries(ZipUtil.getUnsignedLong(fixedSizeData, TOTAL_ENTRIES_OFFSET));
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Re-create the segment zip with a ZIP64-capable standard tool (zip -64 / java.util.zip with ZIP64) and re-upload.
  2. Verify the large archive's integrity end-to-end (checksum before/after upload).
  3. Reduce archive size or entry count below ZIP64 thresholds if the producing pipeline mishandles ZIP64.
  4. Confirm the deep-storage object wasn't truncated by a proxy with a size limit.

Example fix

// before: streaming write that may omit ZIP64
zipOut.putNextEntry(hugeEntry);
// after: ensure ZIP64 mode / precomputed sizes
zipOut.setUseZip64(Zip64Mode.Always);
entry.setSize(precomputedSize);
zipOut.putNextEntry(hugeEntry);
Defensive patterns

Strategy: validation

Validate before calling

if (entryCount > 0xFFFF || totalSize > 0xFFFFFFFFL) {
    verifyZip64StructuresPresent(archiveBytes); // locator + ZIP64 EOCD signature 0x06064b50
}

Try / catch

try {
    zip64Eocd = Zip64EndOfCentralDirectory.read(source, offset);
} catch (PrestoException e) {
    log.error("Missing/corrupt ZIP64 EOCD for %s", source.getId(), e);
    rebuildAndReuploadSegment(segmentId);
}

Prevention

When it happens

Trigger: read() on a file whose Zip64 EOCD record offset (from the locator or EOCD fields) points at data that does not start with the ZIP64 signature — typically a very large archive (>4GB / >65535 entries) whose ZIP64 structures were truncated or written incorrectly.

Common situations: Huge Druid segment zips created or transferred by tools that drop/rewrite ZIP64 extensions, truncated multi-gigabyte uploads, or archives created with streaming writers that emit incorrect ZIP64 offsets.

Understand the failure class

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/3d5264e2e91dfeb6. Report an issue: GitHub.