{"record":{"id":"5f4df561658251f3","repo":"elastic/elasticsearch","slug":"hosts-must-not-be-null-nor-empty","errorCode":null,"errorMessage":"hosts must not be null nor empty","messagePattern":"hosts must not be null nor empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"client/rest/src/main/java/org/elasticsearch/client/RestClient.java","lineNumber":216,"sourceCode":"     * <p>\n     * Prefer this to {@link #builder(HttpHost...)} if you have metadata up front about the nodes.\n     * If you don't either one is fine.\n     */\n    public static RestClientBuilder builder(Node... nodes) {\n        return new RestClientBuilder(nodes == null ? null : Arrays.asList(nodes));\n    }\n\n    /**\n     * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation.\n     * Creates a new builder instance and sets the nodes that the client will send requests to.\n     * <p>\n     * You can use this if you do not have metadata up front about the nodes. If you do, prefer\n     * {@link #builder(Node...)}.\n     * @see Node#Node(HttpHost)\n     */\n    public static RestClientBuilder builder(HttpHost... hosts) {\n        if (hosts == null || hosts.length == 0) {\n            throw new IllegalArgumentException(\"hosts must not be null nor empty\");\n        }\n        List<Node> nodes = Arrays.stream(hosts).map(Node::new).collect(Collectors.toList());\n        return new RestClientBuilder(nodes);\n    }\n\n    /**\n     * Get the underlying HTTP client.\n     */\n    public HttpAsyncClient getHttpClient() {\n        return this.client;\n    }\n\n    /**\n     * Replaces the nodes with which the client communicates.\n     */\n    public synchronized void setNodes(Collection<Node> nodes) {\n        if (nodes == null || nodes.isEmpty()) {\n            throw new IllegalArgumentException(\"nodes must not be null or empty\");","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/client/rest/src/main/java/org/elasticsearch/client/RestClient.java#L198-L234","documentation":"RestClient.builder(HttpHost...) requires at least one host to route requests to; a null or empty array makes the client structurally invalid (no node tuple, no round-robin). The guard rejects both null and zero-length arrays up front.","triggerScenarios":"Calling RestClient.builder() with an empty varargs list, or passing a null HttpHost[] from config that resolved to no hosts.","commonSituations":"Configuration source (env/properties) returned zero hosts; a service-discovery lookup produced an empty list; programmatic helper that built the array conditionally and ended up empty.","solutions":["Ensure the host list is non-empty before building — validate config at load time and fail with a clearer message.","Fall back to a known default host (e.g. localhost:9200) only if that is your intended policy.","If discovery legitimately has zero hosts, delay client creation until at least one host resolves."],"exampleFix":"// before\nHttpHost[] hosts = config.getHosts(); // empty\nRestClient.builder(hosts); // throws\n// after\nif (hosts == null || hosts.length == 0) throw new IllegalStateException(\"no ES hosts configured\");\nRestClient.builder(hosts);","handlingStrategy":"validation","validationCode":"if (hosts == null || hosts.length == 0) throw new IllegalStateException(\"no Elasticsearch hosts configured\");\nRestClient.builder(hosts);","typeGuard":"static boolean hasHosts(HttpHost[] h) { return h != null && h.length > 0; }","tryCatchPattern":null,"preventionTips":["Validate host config at load time and fail with a contextual message.","Delay client construction until discovery resolves at least one host.","Provide a documented default host only if that is your intended behavior."],"tags":["rest-client","validation","config","builder"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}