apache/druid · error · MSQException
UnknownFault.forException(e)
Error message
UnknownFault.forException(e)
What it means
IndexerTableInputSpecSlicer.getTimeline fetches the datasource timeline via coordinator/broker HTTP calls; an IOException during those calls is wrapped as MSQException(e, UnknownFault.forException(e)). It means the table input spec could not learn which segments back the datasource — a connectivity/IO failure against Coordinator or metadata, not a query-logic problem.
Solutions
- Check coordinator availability and health endpoint; retry the query after the coordinator recovers
- Verify network/DNS/TLS connectivity from the MSQ controller task to the coordinator
- Inspect druid.coordination.coordinator config for wrong host/port
- If recurring during upgrades, stagger coordinator restarts away from query launches
Example fix
// handling at call site
try {
timeline = slicer.timeline(spec);
} catch (MSQException e) {
if (e.getCause() instanceof IOException) {
log.warn("Coordinator unreachable, retrying: %s", e.getCause().getMessage());
// retry with backoff
} else { throw e; }
} Defensive patterns
Strategy: retry
Validate before calling
// check coordinator health before submitting table-input MSQ queries
HttpResponse r = get(coordinatorUrl + "/status/health");
if (r.statusCode() != 200) throw new IllegalStateException("Coordinator unhealthy"); Try / catch
try {
timeline = slicer.timeline(spec);
} catch (MSQException e) {
if (e.getCause() instanceof IOException) {
retryWithBackoff(); // coordinator may be restarting
} else { throw e; }
} Prevention
- Avoid launching MSQ queries during coordinator restarts
- Verify peon→coordinator network and DNS connectivity
- Monitor coordinator availability metrics
When it happens
Trigger: Coordinator unreachable or returning connection reset during the timeline request; interrupted HTTP call (IOException) while reading segment metadata; TLS or DNS failures resolving the coordinator host.
Common situations: Coordinator restart or rolling upgrade while an MSQ query starts; network policy blocking peon→coordinator traffic; misconfigured druid.host / coordinator URL in the cluster config.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Asked to remove timeline entry
- Broadcast input number out of range
- BroadcastTablesTooLarge
- Can not supply empty segments as input, please use either…
- CanceledFault(CancellationReason.UNKNOWN)
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/eb8c6231b0689116.
Report an issue: GitHub.
Appendix: source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/indexing/IndexerTableInputSpecSlicer.java:235
// If the task is operating with a REPLACE lock,
// any segment created after the lock was acquired for its interval will not be considered.
final Collection<DataSegment> publishedUsedSegments;
try {
// Additional check as the task action does not accept empty intervals
if (intervals.isEmpty()) {
publishedUsedSegments = Collections.emptySet();
} else {
publishedUsedSegments = taskActionClient.submit(
new RetrieveUsedSegmentsAction(
dataSource,
intervals,
SegmentDetail.none() // Even LoadSpec is not needed, because workers fetch them from the Coordinator.
)
);
}
}
catch (IOException e) {
throw new MSQException(e, UnknownFault.forException(e));
}
int realtimeCount = 0;
// Deduplicate segments, giving preference to published used segments.
// We do this so that if any segments have been handed off in between the two metadata calls above,
// we directly fetch it from deep storage.
Set<DataSegment> unifiedSegmentView = new HashSet<>(publishedUsedSegments);
// Iterate over the realtime segments and segments loaded on the historical
for (ImmutableSegmentLoadInfo segmentLoadInfo : realtimeAndHistoricalSegments) {
Set<DruidServerMetadata> servers = segmentLoadInfo.getServers();
// Filter out only realtime servers. We don't want to query historicals for now, but we can in the future.
// This check can be modified then.
Set<DruidServerMetadata> realtimeServerMetadata
= servers.stream()
.filter(druidServerMetadata -> includeSegmentSource.getUsedServerTypes()
.contains(druidServerMetadata.getType())View on GitHub (pinned to 9b90983fd2)