apache/shenyu · error · NullPointerException
remoteAddress is null
Error message
remoteAddress is null
What it means
TcpBootstrapServer.getIp extracts the host string from the connection's remote SocketAddress, but first asserts the address is non-null, throwing NullPointerException('remoteAddress is null') otherwise. A null remote address means the gateway never obtained peer information for the TCP connection, so no IP-based processing can continue.
Solutions
- Guard the caller: check that the connection/exchange has a non-null remoteAddress before invoking the TCP protocol handling, and drop such connections early.
- Log the channel/connection id at error time to find the client or component producing address-less connections.
- Verify the TCP listener is set up with the standard Reactor Netty transport so remoteAddress is populated on connect.
- Add a connection-level handler that closes sockets without remote address information immediately.
Example fix
// before
String ip = getIp(exchange.getRequest().remoteAddress());
// after
SocketAddress addr = exchange.getRequest().remoteAddress();
if (addr == null) { return; }
String ip = getIp(addr); Defensive patterns
Strategy: type-guard
Validate before calling
SocketAddress addr = connection.remoteAddress();
if (addr == null) { /* drop connection early */ } Type guard
static boolean hasRemoteAddress(SocketAddress addr) {
return addr != null;
}
// usage
if (!hasRemoteAddress(exchange.getRequest().remoteAddress())) { return; } Try / catch
try {
String ip = getIp(socketAddress);
} catch (NullPointerException e) {
if ("remoteAddress is null".equals(e.getMessage())) { /* close/drop the connection */ }
throw e;
} Prevention
- Close connections lacking remote address info at the transport layer before protocol handling.
- Log connection ids to trace which clients produce address-less connections.
When it happens
Trigger: The TCP client/connection handling path invokes getIp with the exchange/connection's remoteAddress (called from the client handler) when that attribute is null — typically a connection that was never fully established or was closed before the address was captured.
Common situations: Race conditions where the peer disconnects immediately after connect; custom/derived channel setups that don't populate remoteAddress; connection accepted through an exotic transport that supplies no socket address.
Related errors
- Unsupported SocketAddress type
- failed to add curator cache.
- Import mcp server config failed:
- Failed to get Swagger document, HTTP status code:
- Response body is empty
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/8a6858b84d49a47e.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-protocol/shenyu-protocol-tcp/src/main/java/org/apache/shenyu/protocol/tcp/TcpBootstrapServer.java:115
LOG.info("Starting proxy client ={}", serverConn);
SocketAddress socketAddress = serverConn.channel().remoteAddress();
ActivityConnectionObserver connectionObserver = new ActivityConnectionObserver("TcpClient");
eventBus.register(connectionObserver);
serverConn.onDispose(() -> eventBus.unregister(connectionObserver));
Mono<Connection> client = connectionContext.getTcpClientConnection(getIp(socketAddress), connectionObserver);
client.subscribe(
clientConn -> bridge.bridge(serverConn, clientConn),
error -> {
LOG.error("Failed to establish client connection for {}", serverConn, error);
eventBus.unregister(connectionObserver);
serverConn.dispose();
}
);
}
private String getIp(final SocketAddress socketAddress) {
if (Objects.isNull(socketAddress)) {
throw new NullPointerException("remoteAddress is null");
}
if (socketAddress instanceof InetSocketAddress) {
return ((InetSocketAddress) socketAddress).getHostString();
}
LOG.error("Unsupported SocketAddress type: {}", socketAddress.getClass().getName());
throw new IllegalArgumentException("Unsupported SocketAddress type: " + socketAddress.getClass().getName());
}
/**
* doOnUpdate.
*
* @param removeList removeList
*/
@Override
public void removeCommonUpstream(final List<DiscoveryUpstreamData> removeList) {
eventBus.post(removeList);
}
View on GitHub (pinned to 567142e072)