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
- Ignore 404 for expired scrolls — treat as successful cleanup; ensure search scroll timeout is long enough for the read to finish
- Check credentials/roles if status is 401/403: the user needs privileges for the _search/scroll endpoint
- Deduplicate cleanup so each scroll ID is cleared exactly once
- Inspect the logged response body for the exact ES error (root_cause) to disambiguate
- 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
- Ensure the ES user has privileges on _search/scroll
- Set scroll TTL longer than the slowest expected read
- Clear each scroll ID exactly once (track opened IDs)
- Read the logged status/body to classify 404 vs 401/403 vs 5xx
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
- Failed to clear scrollId {}, status code={}
- Failed to clear scroll ID: ${scrollId}
- Failed to clear scroll ID: ${scrollId}
- SCROLL_REQUEST_ERROR
- DELETE_PIT_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/d77bf46011e0f776.
Report an issue: GitHub.