{"record":{"id":"45f05fc9f10bd433","repo":"apache/druid","slug":"uri-s-has-no-host","errorCode":null,"errorMessage":"URI[%s] has no host","messagePattern":"URI\\[(.+?)\\] has no host","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/rpc/ServiceLocation.java","lineNumber":87,"sourceCode":"  }\n\n  /**\n   * Create a service location based on a {@link DruidNode}, without a base path.\n   */\n  public static ServiceLocation fromDruidNode(final DruidNode druidNode)\n  {\n    return new ServiceLocation(druidNode.getHost(), druidNode.getPlaintextPort(), druidNode.getTlsPort(), \"\");\n  }\n\n  /**\n   * Create a service location based on a {@link URI}.\n   *\n   * @throws IllegalArgumentException if the URI cannot be mapped to a service location.\n   */\n  public static ServiceLocation fromUri(final URI uri)\n  {\n    if (uri == null || uri.getHost() == null) {\n      throw new IAE(\"URI[%s] has no host\", uri);\n    }\n\n    final String scheme = uri.getScheme();\n    final String host = stripBrackets(uri.getHost());\n    final StringBuilder basePath = new StringBuilder();\n\n    if (uri.getRawPath() != null) {\n      if (uri.getRawQuery() == null && uri.getRawFragment() == null && uri.getRawPath().endsWith(\"/\")) {\n        // Strip trailing slash if the URI has no query or fragment. By convention, this trailing slash is not\n        // part of the service location.\n        basePath.append(uri.getRawPath(), 0, uri.getRawPath().length() - 1);\n      } else {\n        basePath.append(uri.getRawPath());\n      }\n    }\n\n    if (uri.getRawQuery() != null) {\n      basePath.append('?').append(uri.getRawQuery());","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/rpc/ServiceLocation.java#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nServiceLocation loc = ServiceLocation.fromUri(new URI(\"broker.internal:8082\")); // no host\n// after\nServiceLocation loc = ServiceLocation.fromUri(new URI(\"http://broker.internal:8082\"));","handlingStrategy":"validation","validationCode":"if (uri == null || uri.getHost() == null) { throw new IllegalArgumentException(\"URI must include a host: \" + uri); }","typeGuard":"boolean hasHost(URI u) { return u != null && u.getHost() != null; }","tryCatchPattern":"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; }","preventionTips":["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"],"tags":["uri","validation","service-discovery","rpc"],"backgroundTag":"invalid-url","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}