{"record":{"id":"8e50a52c72daaae8","repo":"elastic/elasticsearch","slug":"sniffrequesttimeoutmillis-must-be-greater-than-0","errorCode":null,"errorMessage":"sniffRequestTimeoutMillis must be greater than 0","messagePattern":"sniffRequestTimeoutMillis must be greater than 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"client/sniffer/src/main/java/org/elasticsearch/client/sniff/ElasticsearchNodesSniffer.java","lineNumber":94,"sourceCode":"    public ElasticsearchNodesSniffer(RestClient restClient) {\n        this(restClient, DEFAULT_SNIFF_REQUEST_TIMEOUT, ElasticsearchNodesSniffer.Scheme.HTTP);\n    }\n\n    /**\n     * Creates a new instance of the Elasticsearch sniffer. It will use the provided {@link RestClient} to fetch the hosts\n     * through the nodes info api, the provided sniff request timeout value and scheme.\n     * @param restClient client used to fetch the hosts from elasticsearch through nodes info api. Usually the same instance\n     *                   that is also provided to {@link Sniffer#builder(RestClient)}, so that the hosts are set to the same\n     *                   client that was used to sniff them.\n     * @param sniffRequestTimeoutMillis the sniff request timeout (in milliseconds) to be passed in as a query string parameter\n     *                                  to elasticsearch. Allows to halt the request without any failure, as only the nodes\n     *                                  that have responded within this timeout will be returned.\n     * @param scheme the scheme to associate sniffed nodes with (as it is not returned by elasticsearch)\n     */\n    public ElasticsearchNodesSniffer(RestClient restClient, long sniffRequestTimeoutMillis, Scheme scheme) {\n        this.restClient = Objects.requireNonNull(restClient, \"restClient cannot be null\");\n        if (sniffRequestTimeoutMillis < 0) {\n            throw new IllegalArgumentException(\"sniffRequestTimeoutMillis must be greater than 0\");\n        }\n        this.request = new Request(\"GET\", \"/_nodes/http\");\n        request.addParameter(\"timeout\", sniffRequestTimeoutMillis + \"ms\");\n        this.scheme = Objects.requireNonNull(scheme, \"scheme cannot be null\");\n    }\n\n    /**\n     * Calls the elasticsearch nodes info api, parses the response and returns all the found http hosts\n     */\n    @Override\n    public List<Node> sniff() throws IOException {\n        Response response = restClient.performRequest(request);\n        return readHosts(response.getEntity(), scheme, jsonFactory);\n    }\n\n    static List<Node> readHosts(HttpEntity entity, Scheme scheme, JsonFactory jsonFactory) throws IOException {\n        try (InputStream inputStream = entity.getContent()) {\n            JsonParser parser = jsonFactory.createParser(inputStream);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/client/sniffer/src/main/java/org/elasticsearch/client/sniff/ElasticsearchNodesSniffer.java#L76-L112","documentation":"Constructor guard on ElasticsearchNodesSniffer: the sniff request timeout passed to /_nodes/http?timeout=Nms must not be negative. Note the message says 'greater than 0' but the actual check is `< 0`, so a value of 0 is currently accepted; only strictly negative values trigger this error.","triggerScenarios":"Constructing ElasticsearchNodesSniffer with a negative timeout, or wiring SnifferBuilder defaults through code that computed a negative duration.","commonSituations":"Computing the timeout as 'configured - elapsed' which went negative under load; passing -1 as a sentinel; misreading the message and supplying 0 when you meant 'no timeout' (0 is allowed and means immediate).","solutions":["Pass a non-negative value (>=0); use a small positive value like 1000 (1s) for normal sniffing.","Guard against arithmetic that can go negative before constructing the sniffer.","If you want 'no deadline', use 0 explicitly (the message wording is stricter than the code)."],"exampleFix":"// before\nlong timeout = configuredTimeoutMs - elapsedMs; // can be < 0\nnew ElasticsearchNodesSniffer(client, timeout, Scheme.HTTP);\n// after\nlong timeout = Math.max(0, configuredTimeoutMs - elapsedMs);\nnew ElasticsearchNodesSniffer(client, timeout, Scheme.HTTP);","handlingStrategy":"validation","validationCode":"long t = Math.max(0, configuredTimeoutMs);\nnew ElasticsearchNodesSniffer(client, t, Scheme.HTTP);","typeGuard":"sniffRequestTimeoutMillis >= 0","tryCatchPattern":null,"preventionTips":["Clamp arithmetic on timeouts to a non-negative floor.","Note that 0 is actually accepted despite the message text."],"tags":["sniffer","configuration","validation","timeout"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}