apache/seatunnel · warning
Failed to close SQL cursor: {}
Error message
Failed to close SQL cursor: {} What it means
In EsRestClient.closeSqlCursor, any exception thrown during the HTTP call to /_sql/close (connect timeout, socket timeout, IO error, parse failure) is caught, logged as this warning with the cursor id, and false is returned instead of propagating.
Source
Thrown at seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java:385
Response response = restClient.performRequest(request);
if (response == null) {
log.warn("POST {} response null for cursor: {}", endpoint, cursor);
return false;
}
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String entity = EntityUtils.toString(response.getEntity());
JsonNode jsonNode = JsonUtils.parseObject(entity);
return jsonNode.get("succeeded").asBoolean();
} else {
log.warn(
"POST {} response status code={} for cursor: {}",
endpoint,
response.getStatusLine().getStatusCode(),
cursor);
return false;
}
} catch (Exception ex) {
log.warn("Failed to close SQL cursor: {}", cursor, ex);
return false;
}
}
private ScrollResult getDocsFromSqlResult(
String endpoint, String requestBody, JsonNode columnNodes) {
Request request = new Request("POST", endpoint);
request.setJsonEntity(requestBody);
try {
Response response = restClient.performRequest(request);
if (response == null) {
throw new ElasticsearchConnectorException(
ElasticsearchConnectorErrorCode.SCROLL_REQUEST_ERROR,
"POST " + endpoint + " response null");
}
String entity = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
ObjectNode responseJson = JsonUtils.parseObject(entity);View on GitHub (pinned to cf67b549a7)
Solutions
- Check network connectivity / proxy settings between the SeaTunnel worker and Elasticsearch
- Increase http connection and socket timeout settings
- Ensure TLS configuration is valid if https is used
- Treat as non-fatal: the cursor expires after its keep-alive period
Example fix
// before
// client throws/hides IO errors silently
// after
if (!esRestClient.closeSqlCursor(cursor)) {
LOG.warn("Cursor {} not closed cleanly; it will expire after keep-alive", cursor);
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check connectivity // ensure ES host is reachable before job teardown relies on cursor close
Try / catch
try { client.closeSqlCursor(cursor); } catch (Exception e) { LOG.warn("cursor {} will expire naturally", cursor, e); } Prevention
- Configure reasonable HTTP connect/socket timeouts
- Monitor network reliability to ES nodes
- Don't make cursor close a hard requirement in cleanup logic
When it happens
Trigger: Network failure, connection refused, request timeout, or EntityUtils/JSON processing exception while POSTing to the /_sql/close endpoint.
Common situations: Elasticsearch temporarily unreachable at job shutdown; firewall dropping keep-alive connections; TLS misconfiguration; large timeouts causing socket timeouts.
Related errors
- GET_ES_VERSION_FAILED
- Failed to clear scroll ID: ${scrollId}
- Failed to close SQL cursor: {}
- Failed to fetch metadata from Gravitino for metadata: %s
- fail get tableSchema:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/e0cebd19d9d223c4.
Report an issue: GitHub.