{"record":{"id":"ec554b1b664147b8","repo":"apache/seatunnel","slug":"scroll-request-error","errorCode":"SCROLL_REQUEST_ERROR","errorMessage":"POST ${endpoint} response null","messagePattern":"POST (.+?) response null","errorType":"error_code","errorClass":"EasysearchConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-easysearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/easysearch/client/EasysearchClient.java","lineNumber":372,"sourceCode":"     * @param scrollId the scroll id of the last request\n     * @param scrollTime such as:1m\n     */\n    public ScrollResult searchWithScrollId(String scrollId, String scrollTime) {\n        Map<String, String> param = new HashMap<>();\n        param.put(\"scroll_id\", scrollId);\n        param.put(\"scroll\", scrollTime);\n        ScrollResult scrollResult =\n                getDocsFromScrollRequest(\"/_search/scroll\", JsonUtils.toJsonString(param));\n        return scrollResult;\n    }\n\n    private ScrollResult getDocsFromScrollRequest(String endpoint, String requestBody) {\n        Request request = new Request(\"POST\", endpoint);\n        request.setJsonEntity(requestBody);\n        try {\n            Response response = restClient.performRequest(request);\n            if (response == null) {\n                throw new EasysearchConnectorException(\n                        EasysearchConnectorErrorCode.SCROLL_REQUEST_ERROR,\n                        \"POST \" + endpoint + \" response null\");\n            }\n            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {\n                String entity = EntityUtils.toString(response.getEntity());\n                ObjectNode responseJson = JsonUtils.parseObject(entity);\n\n                JsonNode shards = responseJson.get(\"_shards\");\n                int totalShards = shards.get(\"total\").intValue();\n                int successful = shards.get(\"successful\").intValue();\n                Asserts.check(\n                        totalShards == successful,\n                        String.format(\n                                \"POST %s,total shards(%d)!= successful shards(%d)\",\n                                endpoint, totalShards, successful));\n\n                ScrollResult scrollResult = getDocsFromScrollResponse(responseJson);\n                return scrollResult;","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-easysearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/easysearch/client/EasysearchClient.java#L354-L390","documentation":"EasysearchClient wraps the low-level REST client and throws EasysearchConnectorException with SCROLL_REQUEST_ERROR when a scroll POST returns a null Response object. The low-level RestClient.performRequest is expected to always return a Response or throw IOException, so a null is treated as a protocol-level anomaly and surfaced as a connector failure. This guards the caller from NPEs when dereferencing the status line.","triggerScenarios":"getDocsFromScrollRequest is invoked via scrollResult when a scroll request is issued (first scroll with a query body or continuation scroll with scroll_id) and restClient.performRequest(request) unexpectedly returns null.","commonSituations":"Unusual proxy/interceptor behavior returning null, a broken or misconfigured node behind a load balancer that swallows the response, or misuse of a custom RestClient wrapper in tests.","solutions":["Check network/proxy configuration between SeaTunnel and the Easysearch/Elasticsearch node; a healthy client should throw IOException rather than return null","Verify the endpoint URL built for scroll is valid (no malformed index or scroll_id)","Upgrade/rebuild the connector so the shaded RestClient version matches the server","Enable REST client trace logging (org.apache.http / RestClient) to capture the exchange preceding the null response"],"exampleFix":"// before\nResponse response = restClient.performRequest(request);\nif (response == null) { throw new EasysearchConnectorException(...SCROLL_REQUEST_ERROR...); }\n// after\nResponse response = restClient.performRequest(request);\nObjects.requireNonNull(response, \"scroll response must not be null\");\nif (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { /* retry with backoff */ }","handlingStrategy":"retry","validationCode":"// verify cluster reachable before job\ntry (CloseableHttpResponse r = httpClient.execute(new HttpGet(baseUrl + \"/_cluster/health\"))) {\n  if (r.getStatusLine().getStatusCode() != 200) throw new IllegalStateException(\"cluster unreachable\");\n}","typeGuard":"boolean valid(Response r) { return r != null && r.getStatusLine() != null; }","tryCatchPattern":"try { scrollResult(...); } catch (EasysearchConnectorException e) { if (e.getErrorCode() == SCROLL_REQUEST_ERROR) { backoffRetry(3); } else throw e; }","preventionTips":["Health-check the cluster before starting jobs","Avoid custom proxies/interceptors around RestClient that can return null","Pin compatible RestClient and server versions","Enable wire/trace logging in test environments"],"tags":["http","null-response","scroll","easysearch"],"backgroundTag":"http-request-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}