apache/druid · error · IllegalArgumentException
URI[ ] has no host
Error message
URI[%s] has no host
What it means
ServiceLocation.fromUri() maps a java.net.URI to a ServiceLocation, which requires a host. A null URI or a URI with no host component (e.g., a relative URI like "/status" or scheme-only "localhost:8080" misparsed) throws an IllegalArgumentException.
Solutions
- Ensure the URI string includes scheme and host, e.g., "http://broker:8082".
- Fix strings like "host:port" by prefixing a scheme: new URI("http://" + hostPort).
- Null-check the URI before calling fromUri().
- Validate addresses at config load with a URI parser that requires host.
Example fix
// before
ServiceLocation loc = ServiceLocation.fromUri(new URI("broker.internal:8082")); // no host
// after
ServiceLocation loc = ServiceLocation.fromUri(new URI("http://broker.internal:8082")); Defensive patterns
Strategy: validation
Validate before calling
if (uri == null || uri.getHost() == null) { throw new IllegalArgumentException("URI must include a host: " + uri); } Type guard
boolean hasHost(URI u) { return u != null && u.getHost() != null; } Try / catch
try { return ServiceLocation.fromUri(uri); } catch (IllegalArgumentException e) { if (e.getMessage().endsWith("has no host")) { throw new IllegalArgumentException("Provide scheme-qualified URI like http://host:port, got: " + uri); } throw e; } Prevention
- Always store service addresses as scheme-qualified URIs (http://host:port)
- Prefix 'http://' to host:port config strings before URI parsing
- Null-check URIs from external sources before fromUri()
- Validate address format at config load time
When it happens
Trigger: Calling ServiceLocation.fromUri() with null, with a relative URI lacking authority, or with a string like "host:port" that URI parses as scheme "host" and no host.
Common situations: Parsing service addresses from config strings without a scheme (e.g., "broker:8082" becomes scheme=broker, no host); placeholder/empty URIs in cluster metadata; unvalidated inputs from external services.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Invalid maxAttempts[ ] in retry policy
- One or more values are required for parameter
- Path must start with '/'
- A local input source accepts only one of
- A local input source can set parameter
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/45f05fc9f10bd433.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/rpc/ServiceLocation.java:87
}
/**
* Create a service location based on a {@link DruidNode}, without a base path.
*/
public static ServiceLocation fromDruidNode(final DruidNode druidNode)
{
return new ServiceLocation(druidNode.getHost(), druidNode.getPlaintextPort(), druidNode.getTlsPort(), "");
}
/**
* Create a service location based on a {@link URI}.
*
* @throws IllegalArgumentException if the URI cannot be mapped to a service location.
*/
public static ServiceLocation fromUri(final URI uri)
{
if (uri == null || uri.getHost() == null) {
throw new IAE("URI[%s] has no host", uri);
}
final String scheme = uri.getScheme();
final String host = stripBrackets(uri.getHost());
final StringBuilder basePath = new StringBuilder();
if (uri.getRawPath() != null) {
if (uri.getRawQuery() == null && uri.getRawFragment() == null && uri.getRawPath().endsWith("/")) {
// Strip trailing slash if the URI has no query or fragment. By convention, this trailing slash is not
// part of the service location.
basePath.append(uri.getRawPath(), 0, uri.getRawPath().length() - 1);
} else {
basePath.append(uri.getRawPath());
}
}
if (uri.getRawQuery() != null) {
basePath.append('?').append(uri.getRawQuery());View on GitHub (pinned to 9b90983fd2)