apache/seatunnel · warning

DELETE {} response status code={}, body={} for scroll ID: {}

Error message

DELETE {} response status code={}, body={} for scroll ID: {}

What it means

clearScroll received a real HTTP response but with a non-200 status; it logs endpoint, status code, response body and scroll ID, and returns false. Elasticsearch rejected the DELETE /_search/scroll call — e.g. 404 for an unknown/expired scroll ID, 400 malformed request, or auth failure (401/403). Note that clearing an already-expired scroll returning 404 is normally harmless.

Source

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

        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);
                boolean succeeded = jsonNode.get("succeeded").asBoolean();
                return succeeded;
            } else {
                log.warn(
                        "DELETE {} response status code={}, body={} for scroll ID: {}",
                        endpoint,
                        response.getStatusLine().getStatusCode(),
                        entity,
                        scrollId);
                return false;
            }
        } catch (Exception ex) {
            log.warn("Failed to clear scroll ID: " + scrollId, ex);
            return false;
        }
    }

    /**
     * Close SQL cursor to release server-side resources.
     *
     * @param cursor The SQL cursor to close
     * @return True if the cursor was successfully closed
     */

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Ignore 404 for expired scrolls — treat as successful cleanup; ensure search scroll timeout is long enough for the read to finish
  2. Check credentials/roles if status is 401/403: the user needs privileges for the _search/scroll endpoint
  3. Deduplicate cleanup so each scroll ID is cleared exactly once
  4. Inspect the logged response body for the exact ES error (root_cause) to disambiguate
  5. Retry on transient 5xx with short backoff

Example fix

// before: treat any false as failure
if (!esClient.clearScroll(scrollId)) { throw new RuntimeException("cleanup failed"); }
// after: best-effort cleanup
boolean cleared = esClient.clearScroll(scrollId);
if (!cleared) {
    log.info("Scroll {} not cleared (likely expired); it will time out server-side", scrollId);
}
Defensive patterns

Strategy: fallback

Try / catch

// distinguish expected 404 (expired) from real failures via the logged body
if (!esClient.clearScroll(scrollId)) {
    log.debug("Scroll {} not cleared; likely expired (harmless) or permission issue", scrollId);
}

Prevention

When it happens

Trigger: DELETE /_search/scroll returns 404 (scroll already expired or cleared), 401/403 (bad credentials/permissions), 400 (malformed scroll_id/body), 5xx (cluster error).

Common situations: Scroll TTL elapsed before cleanup ran; same scroll cleared twice (double cleanup in finally + close); user lacking privileges to clear scrolls; cluster restart losing scroll context.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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