{"record":{"id":"d96dd2239b2ba728","repo":"apache/seatunnel","slug":"delete-response-null-for-scroll-id","errorCode":null,"errorMessage":"DELETE {} response null for scroll ID: {}","messagePattern":"DELETE (.+?) response null for scroll ID: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java","lineNumber":325,"sourceCode":"     * @param scrollId The scroll ID to clear\n     * @return True if the scroll was successfully cleared\n     */\n    public boolean clearScroll(String scrollId) {\n        if (StringUtils.isEmpty(scrollId)) {\n            log.warn(\"Attempted to clear scroll with empty scroll ID\");\n            return false;\n        }\n\n        String endpoint = \"/_search/scroll\";\n        Request request = new Request(\"DELETE\", endpoint);\n        Map<String, String> requestBody = new HashMap<>();\n        requestBody.put(\"scroll_id\", scrollId);\n        request.setJsonEntity(JsonUtils.toJsonString(requestBody));\n\n        try {\n            Response response = restClient.performRequest(request);\n            if (response == null) {\n                log.warn(\"DELETE {} response null for scroll ID: {}\", endpoint, scrollId);\n                return false;\n            }\n            String entity = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);\n            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {\n                JsonNode jsonNode = JsonUtils.parseObject(entity);\n                boolean succeeded = jsonNode.get(\"succeeded\").asBoolean();\n                return succeeded;\n            } else {\n                log.warn(\n                        \"DELETE {} response status code={}, body={} for scroll ID: {}\",\n                        endpoint,\n                        response.getStatusLine().getStatusCode(),\n                        entity,\n                        scrollId);\n                return false;\n            }\n        } catch (Exception ex) {\n            log.warn(\"Failed to clear scroll ID: \" + scrollId, ex);","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java#L307-L343","documentation":"EsRestClient.clearScroll logs this when restClient.performRequest returns a null Response for the DELETE /_search/scroll request. The low-level REST client normally throws rather than returning null, so a null response indicates an abnormal/unexpected client state. clearScroll returns false, signaling the scroll was not cleared (possible server-side resource leak).","triggerScenarios":"DELETE /_search/scroll executed and performRequest resolved to null — defensive branch for a client that returned no response object (connection layer anomaly, wrapped/mocked client).","commonSituations":"Custom or shaded RestClient wrapper that returns null instead of throwing on transport failure; testing stubs; edge conditions in the REST client where no response and no exception occur.","solutions":["Treat false from clearScroll as best-effort cleanup; scrolls also expire via the scroll timeout, so set a sane scroll timeout on searches","Check RestClient configuration/proxy for wrappers that can return null responses instead of throwing","Log/capture at the caller: verify cluster connectivity — a real transport problem usually throws instead","Retry clearScroll once with the same scroll ID; clearing is idempotent","Ensure scroll TTL (scroll timeout on the search) is bounded so leaked scrolls self-expire"],"exampleFix":"// before: assume response always non-null\nResponse r = restClient.performRequest(req);\n// after: caller bounds scroll lifetime regardless\nsearchSourceBuilder.scroll(TimeValue.timeValueMinutes(1)); // expired scrolls self-free\nesClient.clearScroll(scrollId); // best-effort","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// clearScroll is best-effort; don't fail the pipeline on cleanup\nboolean cleared = esClient.clearScroll(scrollId);\nif (!cleared) {\n    log.info(\"Scroll {} cleanup unconfirmed; relying on scroll TTL expiry\", scrollId);\n}","preventionTips":["Always set a bounded scroll timeout on searches","Verify no wrapper around RestClient returns null responses","Check connectivity/proxy health if this recurs","Clear scrolls while the client connection is still open"],"tags":["elasticsearch","scroll","null-response","http"],"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"}