What does Quarkus do that would prevent
I'm trying to make Discord4j work in Quarkus, but I encounter some errors.
Basically, I followed Discord4j's tutorial for a basic bot, and it works fine if I run in from a Java main method.
Then, I made my DiscordClient a Quarkus bean, and all hell broke lose. Well, maybe not that much, but suddenly, Reactor Netty can't resolve the discord.com domain anymore (stack available below).
The Quarkus code and the main method call the same code. The only difference is that the Discord token comes from a @ConfigMapping instead of being hard-coded, but the value is correctly injected.
I'm guessing Quarkus (Mutiny?) is customizing the Netty (Reactor Netty?) configuration, but I can't find details about that, or how it would lead to that error.
Can anyone shed some light or share a lead to solve my issue? Any direction will be appreciated, I just don't know Quarkus's entrails enough to know where to begin investigating.
Thanks in advance.
2025-02-12 22:07:18,136 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi]
2025-02-12 22:07:19,424 INFO [dis.cor.DiscordClientBuilder] (Quarkus Main Thread) Discord4J 3.2.6-5-g501ec30 (https://discord4j.com)
2025-02-12 22:07:19,897 WARN [io.net.res.dns.DefaultDnsServerAddressStreamProvider] (d4j-limiter-1) Default DNS servers: [/[2001:4860:4860:0:0:0:0:8888]:53, /[2001:4860:4860:0:0:0:0:8844]:53] (Google Public DNS as a fallback)
2025-02-12 22:07:20,153 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application
Exception in DiscordConfiguration.java:76
74 });
75
→ 76 login.block();
77 return client;
78 }
...
: reactor.core.Exceptions$ReactiveException: java.net.UnknownHostException: Failed to resolve 'discord.com' [A(1)] after 2 queries
at reactor.core.Exceptions.propagate(Exceptions.java:396)
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:97)
at reactor.core.publisher.Mono.block(Mono.java:1742)
...
Caused by: java.net.UnknownHostException: Failed to resolve 'discord.com' [A(1)] after 2 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1150)
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
Error has been observed at the following site(s):
*__checkpoint ⇢ Request to GET /gateway/bot [RequestStream]
*__checkpoint ⇢ Request to GET /gateway/bot [DefaultRouter]
Original Stack Trace:
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1150)
at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:1097)
at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:455)
at io.netty.resolver.dns.DnsResolveContext.access$700(DnsResolveContext.java:70)
at io.netty.resolver.dns.DnsResolveContext$2.operationComplete(DnsResolveContext.java:524)
...
Caused by: io.netty.resolver.dns.DnsNameResolverException: [223: /[2001:4860:4860:0:0:0:0:8844]:53] DefaultDnsQuestion(discord.com. IN A) failed to send a query '223' via UDP (no stack trace available)
Caused by: java.net.SocketException: Network is unreachable: sendto
at java.base/sun.nio.ch.DatagramChannelImpl.send0(Native Method)
at java.base/sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(DatagramChannelImpl.java:1005)
at java.base/sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:966)
at java.base/sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:889)
at io.netty.channel.socket.nio.NioDatagramChannel.doWriteMessage(NioDatagramChannel.java:297)
...
2025-02-12 22:07:20,200 INFO [io.quarkus] (Quarkus Main Thread) mybot stopped in 0.011s
2025-02-12 22:07:18,129 INFO [io.quarkus] (Quarkus Main Thread) mybot 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.18.1) started in 2.662s.
2025-02-12 22:07:18,136 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-02-12 22:07:18,136 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi]
2025-02-12 22:07:19,424 INFO [dis.cor.DiscordClientBuilder] (Quarkus Main Thread) Discord4J 3.2.6-5-g501ec30 (https://discord4j.com)
2025-02-12 22:07:19,897 WARN [io.net.res.dns.DefaultDnsServerAddressStreamProvider] (d4j-limiter-1) Default DNS servers: [/[2001:4860:4860:0:0:0:0:8888]:53, /[2001:4860:4860:0:0:0:0:8844]:53] (Google Public DNS as a fallback)
2025-02-12 22:07:20,153 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application
Exception in DiscordConfiguration.java:76
74 });
75
→ 76 login.block();
77 return client;
78 }
Exception in DiscordConfiguration.java:30
28 log.debug("Producing Discord bot");
29
→ 30 return buildDiscordClient(config.token());
31 }
32
: reactor.core.Exceptions$ReactiveException: java.net.UnknownHostException: Failed to resolve 'discord.com' [A(1)] after 2 queries
at reactor.core.Exceptions.propagate(Exceptions.java:396)
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:97)
at reactor.core.publisher.Mono.block(Mono.java:1742)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration.buildDiscordClient(DiscordConfiguration.java:76)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration.produceBot(DiscordConfiguration.java:30)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration_ProducerMethod_produceBot_aihjzrC3vxo3N-4V44lsyBRtCpQ_Bean.doCreate(Unknown Source)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration_ProducerMethod_produceBot_aihjzrC3vxo3N-4V44lsyBRtCpQ_Bean.create(Unknown Source)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration_ProducerMethod_produceBot_aihjzrC3vxo3N-4V44lsyBRtCpQ_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration_ProducerMethod_produceBot_aihjzrC3vxo3N-4V44lsyBRtCpQ_Bean.get(Unknown Source)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration_ProducerMethod_produceBot_aihjzrC3vxo3N-4V44lsyBRtCpQ_Bean.get(Unknown Source)
at org.keyboardplaying.labs.HabotApplication_Bean.doCreate(Unknown Source)
at org.keyboardplaying.labs.HabotApplication_Bean.create(Unknown Source)
at org.keyboardplaying.labs.HabotApplication_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_ApplicationScoped_ContextInstances.c0(Unknown Source)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_ApplicationScoped_ContextInstances.computeIfAbsent(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:23)
at org.keyboardplaying.labs.HabotApplication_ClientProxy.arc$delegate(Unknown Source)
at org.keyboardplaying.labs.HabotApplication_ClientProxy.run(Unknown Source)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:143)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:77)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:48)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:116)
at java.base/java.lang.Thread.run(Thread.java:1583)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
at reactor.core.publisher.Mono.block(Mono.java:1742)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration.buildDiscordClient(DiscordConfiguration.java:76)
at org.keyboardplaying.labs.discord.config.DiscordConfiguration.produceBot(DiscordConfiguration.java:30)
... 32 more
Caused by: java.net.UnknownHostException: Failed to resolve 'discord.com' [A(1)] after 2 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1150)
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
Error has been observed at the following site(s):
*__checkpoint ⇢ Request to GET /gateway/bot [RequestStream]
*__checkpoint ⇢ Request to GET /gateway/bot [DefaultRouter]
Original Stack Trace:
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1150)
at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:1097)
at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:455)
at io.netty.resolver.dns.DnsResolveContext.access$700(DnsResolveContext.java:70)
at io.netty.resolver.dns.DnsResolveContext$2.operationComplete(DnsResolveContext.java:524)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:583)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:559)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492)
at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636)
at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:629)
at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:118)
at io.netty.resolver.dns.DnsQueryContext.finishFailure(DnsQueryContext.java:343)
at io.netty.resolver.dns.DnsQueryContext.onQueryWriteCompletion(DnsQueryContext.java:264)
at io.netty.resolver.dns.DnsQueryContext.access$600(DnsQueryContext.java:51)
at io.netty.resolver.dns.DnsQueryContext$3.operationComplete(DnsQueryContext.java:255)
at io.netty.resolver.dns.DnsQueryContext$3.operationComplete(DnsQueryContext.java:252)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:557)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492)
at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636)
at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:629)
at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:118)
at io.netty.util.internal.PromiseNotificationUtil.tryFailure(PromiseNotificationUtil.java:64)
at io.netty.channel.ChannelOutboundBuffer.safeFail(ChannelOutboundBuffer.java:754)
at io.netty.channel.ChannelOutboundBuffer.remove0(ChannelOutboundBuffer.java:339)
at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:319)
at io.netty.channel.nio.AbstractNioMessageChannel.doWrite(AbstractNioMessageChannel.java:158)
at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:929)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:359)
at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:893)
at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1319)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:935)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:921)
at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:907)
at io.netty.channel.DefaultChannelPipeline.flush(DefaultChannelPipeline.java:916)
at io.netty.channel.AbstractChannel.flush(AbstractChannel.java:253)
at io.netty.resolver.dns.DnsResolveContext.internalResolve(DnsResolveContext.java:398)
at io.netty.resolver.dns.DnsResolveContext.resolve(DnsResolveContext.java:247)
at io.netty.resolver.dns.DnsNameResolver.resolveNow(DnsNameResolver.java:1302)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllUncached0(DnsNameResolver.java:1286)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllUncached(DnsNameResolver.java:1227)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllNow(DnsNameResolver.java:1156)
at io.netty.resolver.dns.DnsNameResolver.access$600(DnsNameResolver.java:96)
at io.netty.resolver.dns.DnsNameResolver$7.operationComplete(DnsNameResolver.java:1145)
at io.netty.resolver.dns.DnsNameResolver$7.operationComplete(DnsNameResolver.java:1142)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:583)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:559)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492)
at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:185)
at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:95)
at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:30)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:380)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: io.netty.resolver.dns.DnsNameResolverException: [223: /[2001:4860:4860:0:0:0:0:8844]:53] DefaultDnsQuestion(discord.com. IN A) failed to send a query '223' via UDP (no stack trace available)
Caused by: java.net.SocketException: Network is unreachable: sendto
at java.base/sun.nio.ch.DatagramChannelImpl.send0(Native Method)
at java.base/sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(DatagramChannelImpl.java:1005)
at java.base/sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:966)
at java.base/sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:889)
at io.netty.channel.socket.nio.NioDatagramChannel.doWriteMessage(NioDatagramChannel.java:297)
at io.netty.channel.nio.AbstractNioMessageChannel.doWrite(AbstractNioMessageChannel.java:143)
at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:929)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:359)
at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:893)
at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1319)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:935)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:921)
at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:907)
at io.netty.channel.DefaultChannelPipeline.flush(DefaultChannelPipeline.java:916)
at io.netty.channel.AbstractChannel.flush(AbstractChannel.java:253)
at io.netty.resolver.dns.DnsResolveContext.internalResolve(DnsResolveContext.java:398)
at io.netty.resolver.dns.DnsResolveContext.resolve(DnsResolveContext.java:247)
at io.netty.resolver.dns.DnsNameResolver.resolveNow(DnsNameResolver.java:1302)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllUncached0(DnsNameResolver.java:1286)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllUncached(DnsNameResolver.java:1227)
at io.netty.resolver.dns.DnsNameResolver.doResolveAllNow(DnsNameResolver.java:1156)
at io.netty.resolver.dns.DnsNameResolver.access$600(DnsNameResolver.java:96)
at io.netty.resolver.dns.DnsNameResolver$7.operationComplete(DnsNameResolver.java:1145)
at io.netty.resolver.dns.DnsNameResolver$7.operationComplete(DnsNameResolver.java:1142)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:583)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:559)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492)
at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:185)
at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:95)
at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:30)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:380)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
2025-02-12 22:07:20,200 INFO [io.quarkus] (Quarkus Main Thread) mybot stopped in 0.011s
If your Discord4j bot works in plain Java but fails in Quarkus when resolving DNS for discord.com, the issue might be related to Quarkus' network configuration. Try forcing IPv4 by adding System.setProperty("java.net.preferIPv4Stack", "true"); at the start of your code. Also, ensure your Netty and Reactor dependencies are up to date and that Quarkus has proper network permissions. If the issue persists, configure a custom DNS resolver in Reactor Netty!!! :)