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
EndOfCentralDirectoryRecord.read reads the fixed 22-byte EOCD structure and requires it to start with signature 0x06054b50. If the bytes located by findEndOfCentralDirectoryRecord do not begin with that signature, the record is malformed and DRUID_SEGMENT_LOAD_ERROR is thrown.
Source
Thrown at presto-druid/src/main/java/com/facebook/presto/druid/zip/EndOfCentralDirectoryRecord.java:53
private EndOfCentralDirectoryRecord()
{
}
/**
* Read the end of central directory record from the input stream and parse {@link ZipFileData}
* from it.
*/
public static void read(ZipFileData zipFileData, DataInputSource dataInputSource, long offset)
throws IOException
{
long position = offset;
byte[] fixedSizeData = new byte[FIXED_DATA_SIZE];
dataInputSource.readFully(position, fixedSizeData, 0, FIXED_DATA_SIZE);
position += FIXED_DATA_SIZE;
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));
}
byte[] comment = new byte[ZipUtil.getUnsignedShort(fixedSizeData, COMMENT_LENGTH_OFFSET)];
if (comment.length > 0) {
dataInputSource.readFully(position, comment, 0, comment.length);
}
short diskNumber = ZipUtil.get16(fixedSizeData, DISK_NUMBER_OFFSET);
short centralDirectoryDisk = ZipUtil.get16(fixedSizeData, CD_DISK_OFFSET);
short entriesOnDisk = ZipUtil.get16(fixedSizeData, DISK_ENTRIES_OFFSET);
short totalEntries = ZipUtil.get16(fixedSizeData, TOTAL_ENTRIES_OFFSET);
int centralDirectorySize = ZipUtil.get32(fixedSizeData, CD_SIZE_OFFSET);
int centralDirectoryOffset = ZipUtil.get32(fixedSizeData, CD_OFFSET_OFFSET);
if (diskNumber == -1 || centralDirectoryDisk == -1 || entriesOnDisk == -1
|| totalEntries == -1 || centralDirectorySize == -1 || centralDirectoryOffset == -1) {
zipFileData.setMaybeZip64(true);
}
zipFileData.setComment(comment);
zipFileData.setCentralDirectorySize(ZipUtil.getUnsignedInt(fixedSizeData, CD_SIZE_OFFSET));View on GitHub (pinned to 55bb57d202)
Solutions
- Re-upload the segment zip after verifying it with `unzip -t`.
- Rebuild the archive with a standard tool if it contains nonstandard comments/data known to trip scanners.
- Compare checksums of the stored object against the producer's to pinpoint when corruption occurred.
- Retry reading from a different replica if deep storage provides multiple.
Example fix
// before var eocd = EndOfCentralDirectoryRecord.read(dataInputSource, offset); // after: verify tail bytes before parsing long size = dataInputSource.getSize(); checkState(size >= offset + 22, "EOCD offset %s out of range for %s", offset, dataInputSource.getId()); var eocd = EndOfCentralDirectoryRecord.read(dataInputSource, offset);
Defensive patterns
Strategy: validation
Validate before calling
if (offset + 22 > dataInputSource.getSize()) {
throw new IllegalStateException("EOCD offset out of range: " + offset);
} Try / catch
try {
eocd = EndOfCentralDirectoryRecord.read(source, offset);
} catch (PrestoException e) {
log.error("Malformed EOCD in %s at offset %s", source.getId(), offset, e);
retryWithReplicaOrReIngest(segmentId);
} Prevention
- Avoid archives with huge or binary file comments that can confuse EOCD scanning.
- Validate archives at upload time with unzip -t or a pure-Java probe.
- Keep multiple replicas and fall back on read failure.
When it happens
Trigger: read(offset) called with an offset whose 22 bytes lack the EOCD signature — typically when a backwards scan matched a false signature inside a ZIP comment or file data, or the region was corrupted.
Common situations: Zips with file comments or embedded data containing the EOCD signature bytes causing mislocation, corruption in the final 64KB of the file, or partial downloads that cut the record in half while keeping an earlier false-positive signature.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- DRUID_SEGMENT_LOAD_ERROR
- DRUID_SEGMENT_LOAD_ERROR
- DRUID_SEGMENT_LOAD_ERROR
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
- DRUID_BROKER_RESULT_ERROR
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/ad0ff3abacbbc20c.
Report an issue: GitHub.