apache/druid · error · SegmentMissingException
Null cursor factory found. Probably trying to issue a query
Error message
Null cursor factory found. Probably trying to issue a query against a segment being memory unmapped.
What it means
TopNQueryEngine.query obtains a CursorFactory from the segment via segment.as(CursorFactory.class). A null result means the underlying segment (often a memory-mapped/MMappedIndex) has been released/unmapped, so query execution cannot proceed; Druid throws SegmentMissingException to signal the segment is gone and the query should be retried against a valid segment.
Source
Thrown at processing/src/main/java/org/apache/druid/query/topn/TopNQueryEngine.java:87
{
this.bufferPool = bufferPool;
}
/**
* Do the thing - process a {@link Segment} into a {@link Sequence} of {@link TopNResultValue}, with one of the
* fine {@link TopNAlgorithm} available chosen based on the type of column being aggregated. The algorithm provides a
* mapping function to process rows from the adapter {@link Cursor} to apply {@link AggregatorFactory} and create or
* update {@link TopNResultValue}
*/
public Sequence<Result<TopNResultValue>> query(
TopNQuery query,
final Segment segment,
@Nullable final TopNQueryMetrics queryMetrics
)
{
final CursorFactory cursorFactory = segment.as(CursorFactory.class);
if (cursorFactory == null) {
throw new SegmentMissingException(
"Null cursor factory found. Probably trying to issue a query against a segment being memory unmapped."
);
}
final CursorBuildSpec buildSpec = makeCursorBuildSpec(query, queryMetrics);
final CursorHolder cursorHolder = cursorFactory.makeCursorHolder(buildSpec);
// Once we have a cursorHolder, we need to either return a Sequence, or close it immediately.
try {
if (cursorHolder.isPreAggregated()) {
query = query.withAggregatorSpecs(Preconditions.checkNotNull(cursorHolder.getAggregatorsForPreAggregated()));
}
final Cursor cursor = cursorHolder.asCursor();
if (cursor == null) {
return Sequences.withBaggage(Sequences.empty(), cursorHolder);
}
final TimeBoundaryInspector timeBoundaryInspector = segment.as(TimeBoundaryInspector.class);View on GitHub (pinned to 9b90983fd2)
Solutions
- Retry the query — Druid clusters normally route to a live replica and the transient unmap resolves
- Verify the segment still exists on the coordinator and is served by a historical node
- Check historical logs for segment drop/handoff storms; tune druid.server.http numThreads / unmap caching
- If reproducible on a specific segment type, query a datasource/segment backed by a cursor-capable adapter
Example fix
// before
Segment segment = dataSourceView.get(segmentId); // may be unmapped
queryEngine.query(query, segment, null); // throws SegmentMissingException
// after
try {
queryEngine.query(query, segment, null);
} catch (SegmentMissingException e) {
// retry against refreshed segment/replica
} Defensive patterns
Strategy: retry
Validate before calling
CursorFactory cursorFactory = segment.as(CursorFactory.class);
if (cursorFactory == null) { /* segment missing; refresh segment reference and retry */ } Type guard
boolean isQueryable(Segment segment) {
return segment != null && segment.as(CursorFactory.class) != null;
} Try / catch
try {
return topNQueryEngine.query(query, segment, metrics);
} catch (SegmentMissingException e) {
// segment unmapped; retry via broker or reload segment reference
return retryQuery(query);
} Prevention
- Route queries through the broker so it retries on live replicas
- Avoid holding Segment references across long delays; re-fetch before querying
- Monitor historical nodes for segment unmap/handoff churn
- Pin query execution away from segments scheduled for dropping via coordinator rules
When it happens
Trigger: Issuing a topN query while the historical node is dropping or swapping the segment — memory unmapping races with query execution; also when querying a segment type that cannot adapt to CursorFactory (e.g. a metadata-only or realtime segment without cursor support).
Common situations: Historical server under segment load/replication balancing unmaps segments during queries; query sent to a druid node already closing the segment after a segment-handoff; hitting a 'zombie' realtime task segment being shut down.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Unknown type[%s] for metric[%s]
- Cannot operate on a dimension with no dictionary
- Cannot operate on a dimension with unknown cardinality
- Got a null result! Segments are missing!
- Query type '%s' does not support returning results as arrays
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/7a11f3ffb6fcb250.
Report an issue: GitHub.