prestodb/presto · critical · PrestoException

DRUID_SEGMENT_LOAD_ERROR

DRUID_SEGMENT_LOAD_ERROR

Error message

failed to load druid segment

What it means

DruidSegmentReader's constructor opens a Druid segment file, loads its columns, and creates ColumnValueSelectors wrapped in column readers. Any IOException during segment loading is rethrown as DRUID_SEGMENT_LOAD_ERROR with the generic message 'failed to load druid segment', so the connector cannot read the segment's data.

Solutions

  1. Inspect the underlying IOException cause (enable debug logging) and verify the segment file exists and is intact at the deep-storage path returned by DruidSegmentInfo.getDeepStoragePath().
  2. Verify the segment in Druid: query the Druid metadata for the segment and re-fetch/re-download it from deep storage; kill and re-ingest the segment if corrupted.
  3. Check filesystem/network access from the Presto coordinator/worker to deep storage (S3/HDFS/GS credentials, connectivity).
  4. Clear the segment cache if present and retry, so the segment is freshly pulled from deep storage.

Example fix

// before (read without checking segment availability)
DruidSegmentReader reader = new DruidSegmentReader(segmentFile, columns, types);

// after (validate the segment is loadable first)
if (!segmentFile.exists() || segmentFile.length() == 0) {
    throw new PrestoException(DRUID_SEGMENT_LOAD_ERROR, "Segment file missing or empty: " + segmentFile);
}
DruidSegmentReader reader = new DruidSegmentReader(segmentFile, columns, types);
Defensive patterns

Strategy: try-catch

Validate before calling

Path segmentPath = Paths.get(segmentFileLocation);
if (!Files.isReadable(segmentPath) || Files.size(segmentPath) == 0) {
    throw new PrestoException(DRUID_SEGMENT_LOAD_ERROR, "Segment file missing, unreadable, or empty: " + segmentFileLocation);
}
// optionally: validate magic/header bytes of the segment file before loading

Try / catch

try {
    DruidSegmentReader reader = new DruidSegmentReader(file, columns, types);
} catch (PrestoException e) {
    if (DRUID_SEGMENT_LOAD_ERROR.getCode().equals(e.getErrorCode())) {
        log.error(e.getCause(), "Segment load failed; invalidating cache for %s", file);
        // evict cached copy, re-fetch from deep storage, retry once
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Constructing DruidSegmentReader over a segment file that cannot be read: corrupted/truncated segment file, missing file at the resolved deep-storage path, network/filesystem failure while streaming from S3/HDFS/GS, or an IO error while building column value selectors.

Common situations: Incomplete or corrupted segments in deep storage (e.g. failed Druid ingestion left partial files); deep-storage path misconfiguration so the local cache points at a nonexistent file; HDFS/S3 outage or credentials issue while fetching; segment deleted between planning and read.

Related errors


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

Appendix: source

Thrown at presto-druid/src/main/java/com/facebook/presto/druid/segment/DruidSegmentReader.java:66

    public DruidSegmentReader(SegmentIndexSource segmentIndexSource, List<ColumnHandle> columns)
    {
        try {
            queryableIndex = segmentIndexSource.loadIndex(columns);
            totalRowCount = queryableIndex.getNumRows();
            ImmutableMap.Builder<String, ColumnReader> selectorsBuilder = ImmutableMap.builder();
            for (ColumnHandle column : columns) {
                DruidColumnHandle druidColumn = (DruidColumnHandle) column;
                String columnName = druidColumn.getColumnName();
                Type type = druidColumn.getColumnType();
                BaseColumn baseColumn = queryableIndex.getColumnHolder(columnName).getColumn();
                ColumnValueSelector<?> valueSelector = baseColumn.makeColumnValueSelector(new SimpleReadableOffset());
                selectorsBuilder.put(columnName, createColumnReader(type, valueSelector));
            }
            columnValueSelectors = selectorsBuilder.build();
        }
        catch (IOException e) {
            throw new PrestoException(DRUID_SEGMENT_LOAD_ERROR, "failed to load druid segment");
        }
    }

    @Override
    public int nextBatch()
    {
        // TODO: dynamic batch sizing
        currentBatchSize = toIntExact(min(BATCH_SIZE, totalRowCount - currentPosition));
        currentPosition += currentBatchSize;
        return currentBatchSize;
    }

    @Override
    public Block readBlock(Type type, String columnName)
    {
        return columnValueSelectors.get(columnName).readBlock(type, currentBatchSize);
    }
}

View on GitHub (pinned to 55bb57d202)