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
The timeseries engine requires a non-null CursorFactory to read the segment. A null cursor factory means the segment's data was released from memory (mmap unmapped / dropped while query in flight), so Druid throws SegmentMissingException instead of failing obscurely later.
Source
Thrown at processing/src/main/java/org/apache/druid/query/timeseries/TimeseriesQueryEngine.java:97
final @Global NonBlockingPool<ByteBuffer> bufferPool
)
{
this.bufferPool = bufferPool;
}
/**
* Run a single-segment, single-interval timeseries query on a particular adapter. The query must have been
* scoped down to a single interval before calling this method.
*/
public Sequence<Result<TimeseriesResultValue>> process(
TimeseriesQuery query,
final CursorFactory cursorFactory,
@Nullable TimeBoundaryInspector timeBoundaryInspector,
@Nullable final TimeseriesQueryMetrics timeseriesQueryMetrics
)
{
if (cursorFactory == null) {
throw new SegmentMissingException(
"Null cursor factory found. Probably trying to issue a query against a segment being memory unmapped."
);
}
final Interval interval = Iterables.getOnlyElement(query.getIntervals());
final Granularity gran = query.getGranularity();
final CursorHolder cursorHolder = cursorFactory.makeCursorHolder(makeCursorBuildSpec(query, timeseriesQueryMetrics));
if (cursorHolder.isPreAggregated()) {
query = query.withAggregatorSpecs(Preconditions.checkNotNull(cursorHolder.getAggregatorsForPreAggregated()));
}
try {
final Sequence<Result<TimeseriesResultValue>> result;
if (query.context().getVectorize().shouldVectorize(cursorHolder.canVectorize())) {
result = processVectorized(query, cursorHolder, timeBoundaryInspector, interval, gran);
} else {
result = processNonVectorized(query, cursorHolder, timeBoundaryInspector, interval, gran);View on GitHub (pinned to 9b90983fd2)
Solutions
- Retry the query — the segment will be resolved from another replica or after the swap completes
- Enable query retries on timeout/segment-missing in the broker (druid.broker.balancing / retry policy)
- Avoid dropping/unloading segments while queries are in flight (drain queries before segment drop)
- Check cluster stability: node failures, disk eviction, or aggressive segment drop policies
Example fix
// before
Sequence<Result<TimeseriesResultValue>> s = engine.process(query, null, null, null); // throws
// after
if (cursorFactory == null) {
// retry against another replica / fail gracefully with SegmentMissingException handling
throw new QueryInterruptedException(new ResourceLimitException("segment unavailable"));
}
Sequence<Result<TimeseriesResultValue>> s = engine.process(query, cursorFactory, null, null); Defensive patterns
Strategy: retry
Validate before calling
if (cursorFactory == null) { /* segment unavailable: retry or reroute before processing */ } Type guard
static boolean segmentAvailable(@Nullable CursorFactory cf) { return cf != null; } Try / catch
try { return engine.process(query, cursorFactory, tbi, metrics); }
catch (SegmentMissingException e) { return retryWithBackoff(query, 3); } Prevention
- Enable broker query retry on segment-missing
- Drain queries before dropping segments
- Monitor segment drop/handoff rates during rebalances
When it happens
Trigger: Issuing a TimeseriesQuery against a segment that is being swapped out of memory or dropped concurrently (real-time task handoff, historical segment drop, rebalance during query).
Common situations: Cluster under segment-replication/rebalance churn, historicals dropping segments during rolling restarts, real-time task handing off while queries are executing, cache eviction racing with a query.
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
- Could not create group mapping [%s] due to concurrent update
- Could not delete group mapping [%s] due to concurrent update
- Could not create role [%s] due to concurrent update contenti
- Could not delete role [%s] due to concurrent update contenti
- Could not assign role [%s] to user [%s] due to concurrent up
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/4d824fa705bbc5b6.
Report an issue: GitHub.