apache/seatunnel · info

Attempted to clear scroll with empty scroll ID

Error message

Attempted to clear scroll with empty scroll ID

What it means

Guard in EsRestClient.clearScroll: called with a null or empty scrollId, so the client logs a warning and returns false without issuing any DELETE to Elasticsearch. Clearing a scroll with no ID is meaningless — the method short-circuits to avoid a pointless HTTP round trip. The scroll simply remains uncleared (a resource leak if the ID was lost).

Solutions

  1. Capture the scroll ID from the initial search response before any code path can lose it
  2. Skip clearScroll when no ID exists instead of treating false as an error: if (scrollId != null) client.clearScroll(scrollId)
  3. Trace why the ID was empty — check whether the initial search actually used scroll and succeeded
  4. On close paths, only clear scrolls that were actually opened (track them in a set)

Example fix

// before
boolean cleared = esClient.clearScroll(scrollId);
// after
if (scrollId != null && !scrollId.isEmpty()) {
    boolean cleared = esClient.clearScroll(scrollId);
}
Defensive patterns

Strategy: validation

Validate before calling

boolean shouldClear = scrollId != null && !scrollId.isEmpty();

Type guard

boolean hasScrollId(String id) { return id != null && !id.isEmpty(); }

Prevention

When it happens

Trigger: clearScroll(scrollId) invoked with null or "" — typically the scroll ID was never captured from a search response, or the search that created it never ran/failed before returning an ID.

Common situations: Search path returned no scroll ID on an empty or failed initial search but cleanup still runs in finally; code path that clears scrolls on close even when scrolling was disabled; refactoring changed how the ID is passed and it is now dropped.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/d1e450d27c42c683. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java:312

        return getDocsFromScrollRequest("/_search/scroll", JsonUtils.toJsonString(param));
    }

    public ScrollResult searchWithSql(String scrollId, JsonNode columnNodes) {
        Map<String, String> param = new HashMap<>();
        param.put("cursor", scrollId);
        String endpoint = "/_sql?format=json";
        return getDocsFromSqlResult(endpoint, JsonUtils.toJsonString(param), columnNodes);
    }

    /**
     * Clear scroll context to release server-side resources.
     *
     * @param scrollId The scroll ID to clear
     * @return True if the scroll was successfully cleared
     */
    public boolean clearScroll(String scrollId) {
        if (StringUtils.isEmpty(scrollId)) {
            log.warn("Attempted to clear scroll with empty scroll ID");
            return false;
        }

        String endpoint = "/_search/scroll";
        Request request = new Request("DELETE", endpoint);
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("scroll_id", scrollId);
        request.setJsonEntity(JsonUtils.toJsonString(requestBody));

        try {
            Response response = restClient.performRequest(request);
            if (response == null) {
                log.warn("DELETE {} response null for scroll ID: {}", endpoint, scrollId);
                return false;
            }
            String entity = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                JsonNode jsonNode = JsonUtils.parseObject(entity);

View on GitHub (pinned to cf67b549a7)