eclipse-vertx/vert.x · error · IllegalStateException
address not specified
Error message
address not specified
What it means
sendReply is invoked when replying to a received message; the reply message must carry a destination address. EventBusImpl.sendReply throws this IllegalStateException when replyMessage.address() is null, i.e. a reply is being sent but no reply address was captured from the incoming message.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/eventbus/impl/EventBusImpl.java:359
}
private <T> void removeLocalRegistration(HandlerHolder<T> holder) {
String address = holder.getHandler().address;
handlerMap.compute(address, (key, val) -> {
if (val == null) {
return null;
}
ConcurrentCyclicSequence<HandlerHolder> next = val.remove(holder);
return next.size() == 0 ? null : next;
});
if (holder.setRemoved() && holder.getContext().deploymentID() != null) {
holder.getContext().removeCloseHook(holder.getHandler());
}
}
protected <T> void sendReply(MessageImpl<?, T> replyMessage, DeliveryOptions options, ReplyHandler<T> replyHandler) {
if (replyMessage.address() == null) {
throw new IllegalStateException("address not specified");
} else {
sendOrPubInternal(new SendContext<>(vertx.getOrCreateContext(), replyMessage, options, replyHandler));
}
}
protected <T> void sendOrPub(ContextInternal ctx, MessageImpl<?, T> message, DeliveryOptions options, Promise<Void> writePromise) {
sendLocally(message, writePromise);
}
protected <T> void sendOrPub(SendContext<T> sendContext) {
sendOrPub(sendContext.ctx, sendContext.message, sendContext.options, sendContext);
}
protected <T> void sendLocally(MessageImpl<?, T> message, Promise<Void> writePromise) {
ReplyException failure = deliverMessageLocally(message);
if (failure != null) {
writePromise.tryFail(failure);
} else {View on GitHub (pinned to fb308bd8c3)
Solutions
- Reply using message.reply(body) / replyAndRequest() on the received Message instead of calling internal sendReply.
- If building a reply message manually, set its address (typically via generateReplyAddress() or the incoming message's replyAddress).
- Avoid subclassing/patching EventBus internals; use DeliveryOptions and the public Message API.
Example fix
// before MessageImpl reply = new MessageImpl<>(null, body, options, bus); // null address bus.sendReply(reply, options, handler); // after message.reply(body, new DeliveryOptions());
Defensive patterns
Strategy: type-guard
Validate before calling
Objects.requireNonNull(replyMessage.address(), "reply address must be set before sendReply");
Type guard
boolean canReply(Message<?, ?> m) {
return m.address() != null || m.replyAddress() != null;
} Try / catch
try {
message.reply(body);
} catch (IllegalStateException e) {
// no reply address; log and fall back to normal send
} Prevention
- Use the public Message.reply()/replyAndRequest() API instead of internal sendReply
- Never construct reply MessageImpl instances manually
- In custom EventBus subclasses, always assign generateReplyAddress() to reply messages
When it happens
Trigger: Constructing a MessageImpl manually with a null address and passing it to sendReply/internal reply APIs; replying through a hand-rolled ReplyHandler without a generateReplyAddress()-assigned reply address; misuse of protected internal reply paths in custom EventBus subclasses.
Common situations: Custom EventBus implementations or deep-integration code that bypass Message.reply()/fail() and call internal methods directly; tests fabricating reply messages without setting the reply address.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Already a codec registered with name
- Already a default codec registered for class
- Already started
- Event Bus is not started
- Can't register a system codec
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/0b8e5d2d156e32f0.
Report an issue: GitHub.