apache / apache/druid

broker metadata refresh exception, This leads to an infinite loop of retries, and the broker is unable to retrieve the corresponding metadata.

Open
#19,440 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
14.1k
Forks
3.8k
Avg merge
2d 58m
Merged PRs (30d)
233

Description

The issue occurred in version Druid 28.0.1

broker keeps reporting errors when loading and refreshing segments. After calling the indexer and receiving an error, for some reason, the indexer fails to query the datasource. This causes the broker's segment cache to refresh and retry indefinitely, resulting in abnormal metadata cache.

I believe this is an issue of robustness that needs to be addressed.

Historical issue : https://github.com/apache/druid/issues/16936

When `indexer.getBundle()` is null, an IAE (IllegalArgumentException) is thrown. After the broker captures this exception, it will be added back to the refresh queue, leading to repeated retries and ultimately causing an infinite loop.

@VisibleForTesting
DatasourceBundle getBundle(final Query query)
{
final DataSourceAnalysis analysis = query.getDataSource().getAnalysis();

final TableDataSource table =
analysis.getBaseTableDataSource()
.orElseThrow(() -> new ISE("Cannot handle datasource: %s", query.getDataSource()));

final DatasourceBundle bundle;

synchronized (this) {
bundle = datasourceBundles.get(table.getName());
}

if (bundle == null) {
throw new IAE("Could not find segment walker for datasource [%s]", table.getName());
}

return bundle;
}

The following code will result in an infinite loop.

refresh(segmentsToRefresh, dataSourcesToRebuild);

initialized.countDown();
}
catch (InterruptedException e) {
// Fall through.
throw e;
}
catch (Exception e) {
log.warn(e, "Metadata refresh failed, trying again soon.");

synchronized (lock) {
// Add our segments and dataSources back to their refresh and rebuild lists.
segmentsNeedingRefresh.addAll(segmentsToRefresh);
dataSourcesNeedingRebuild.addAll(dataSourcesToRebuild);
lastFailure = System.currentTimeMillis();
}
}

The error stack is as follows:

broker.log
[DruidSchema-Cache-0][ROOT][org.apache.druid.client.JsonParserIterator] Query [12907933-7fdd-4c09-889c-f0c774a0ec91] to host [xx.xx.xx.xx:26204] interrupted
org.apache.druid.query.QueryException: Could not find segment walker for datasource [tbl_data_res_a]
at sun.reflect.GeneratedConstructorAccessor411.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_452]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_452]
at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:124) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:291) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:288) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:454) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer.deserializeFromObject(ThrowableDeserializer.java:65) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4569) ~[jackson-databind-2.12.7.jar:2.12.7]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2798) ~[jackson-databind-2.12.7.jar:2.12.7]
at org.apache.druid.client.JsonParserIterator.init(JsonParserIterator.java:186) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.client.JsonParserIterator.hasNext(JsonParserIterator.java:92) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.BaseSequence.toYielder(BaseSequence.java:70) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MappedSequence.toYielder(MappedSequence.java:49) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MergeSequence.lambda$toYielder$0(MergeSequence.java:66) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MappingAccumulator.accumulate(MappingAccumulator.java:40) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.BaseSequence.accumulate(BaseSequence.java:44) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MappedSequence.accumulate(MappedSequence.java:43) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MergeSequence.toYielder(MergeSequence.java:63) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.LazySequence.toYielder(LazySequence.java:46) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:88) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:84) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.SequenceWrapper.wrap(SequenceWrapper.java:55) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence.toYielder(WrappingSequence.java:83) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MergeSequence.lambda$toYielder$0(MergeSequence.java:66) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.BaseSequence.accumulate(BaseSequence.java:44) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MergeSequence.toYielder(MergeSequence.java:63) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.query.RetryQueryRunner$1.toYielder(RetryQueryRunner.java:133) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.common.guava.CombiningSequence.toYielder(CombiningSequence.java:78) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MappedSequence.toYielder(MappedSequence.java:49) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.MappedSequence.toYielder(MappedSequence.java:49) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:88) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:84) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.query.CPUTimeMetricQueryRunner$1.wrap(CPUTimeMetricQueryRunner.java:77) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence.toYielder(WrappingSequence.java:83) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:88) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence$2.get(WrappingSequence.java:84) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.SequenceWrapper.wrap(SequenceWrapper.java:55) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.WrappingSequence.toYielder(WrappingSequence.java:83) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.Yielders.each(Yielders.java:32) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.sql.calcite.schema.SegmentMetadataCache.refreshSegmentsForDataSource(SegmentMetadataCache.java:796) ~[druid-sql-28.0.1-htrunk50.jar:?]
at org.apache.druid.sql.calcite.schema.SegmentMetadataCache.refreshSegments(SegmentMetadataCache.java:744) ~[druid-sql-28.0.1-htrunk50.jar:?]
at org.apache.druid.sql.calcite.schema.SegmentMetadataCache.refresh(SegmentMetadataCache.java:467) ~[druid-sql-28.0.1-htrunk50.jar:?]
at org.apache.druid.sql.calcite.schema.SegmentMetadataCache.lambda$startCacheExec$1(SegmentMetadataCache.java:409) ~[druid-sql-28.0.1-htrunk50.jar:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_452]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_452]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_452]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_452]
at java.lang.Thread.run(Thread.java:750) ~[?:1.8.0_452]
2026-05-06 07:02:37,161 WARN [DruidSchema-Cache-0][ROOT][org.apache.druid.server.QueryLifecycle] Exception while processing queryId [12907933-7fdd-4c09-889c-f0c774a0ec91]
org.apache.druid.query.QueryInterruptedException: Could not find segment walker for datasource [tbl_data_res_a]
at org.apache.druid.client.JsonParserIterator.convertException(JsonParserIterator.java:276) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.client.JsonParserIterator.init(JsonParserIterator.java:186) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.client.JsonParserIterator.hasNext(JsonParserIterator.java:92) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.java.util.common.guava.BaseSequence.toYielder(BaseSequence.java:70) ~[druid-processing-28.0.1-htrunk50.jar:?]

indexer.log
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.servlets.QoSFilter.doFilter(QoSFilter.java:202) ~[jetty-servlets-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552) ~[jetty-servlet-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505) ~[jetty-servlet-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:772) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:59) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:181) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) ~[jetty-server-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:555) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:410) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:164) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[jetty-io-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) ~[jetty-util-9.4.56.v20240826.jar:9.4.56.v20240826]
at java.lang.Thread.run(Thread.java:750) ~[?:1.8.0_452]
Caused by: org.apache.druid.query.QueryInterruptedException: Could not find segment walker for datasource [tbl_data_res_a]
... 86 more
Caused by: org.apache.druid.java.util.common.IAE: Could not find segment walker for datasource [tbl_data_res_a]
at org.apache.druid.segment.realtime.appenderator.UnifiedIndexerAppenderatorsManager.getBundle(UnifiedIndexerAppenderatorsManager.java:376) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.segment.realtime.appenderator.UnifiedIndexerAppenderatorsManager.getQueryRunnerForSegments(UnifiedIndexerAppenderatorsManager.java:357) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.indexing.overlord.ThreadingTaskRunner.getQueryRunnerForSegments(ThreadingTaskRunner.java:550) ~[druid-indexing-service-28.0.1-htrunk50.jar:?]
at org.apache.druid.query.spec.MultipleSpecificSegmentSpec.lookup(MultipleSpecificSegmentSpec.java:77) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.query.BaseQuery.getRunner(BaseQuery.java:119) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.query.QueryPlus.run(QueryPlus.java:149) ~[druid-processing-28.0.1-htrunk50.jar:?]
at org.apache.druid.server.QueryLifecycle.execute(QueryLifecycle.java:285) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.server.QueryResource$QueryResourceQueryResultPusher$1.start(QueryResource.java:512) ~[druid-server-28.0.1-htrunk50.jar:?]
at org.apache.druid.server.QueryResultPusher.push(QueryResultPusher.java:121) ~[druid-server-28.0.1-htrunk50.jar:?]
... 85 more

Contributor guide

Open the contributing guide

Research direction

Start with SegmentMetadataCache.refresh, refreshSegments, refreshSegmentsForDataSource, and the getBundle method shown in the issue; trace how the missing DatasourceBundle exception is handled and requeued. Use the reported broker and indexer logs to reproduce the failure, then verify that a missing bundle no longer causes indefinite metadata-refresh retries.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.