apache/seatunnel · warning

POST response null for cursor

Error message

POST {} response null for cursor: {}

What it means

EsRestClient.closeSqlCursor logs this when performRequest returns a null Response for the POST /_sql/close request that releases an SQL cursor. As with clearScroll's null branch, the client returned no response object, so the cursor could not be confirmed closed and the method returns false. The cursor should time out server-side eventually.

Solutions

  1. Verify Elasticsearch connectivity and any proxy in front of it that could swallow requests
  2. Check whether a custom RestClient wrapper returns null instead of throwing; fix the wrapper to surface transport exceptions
  3. Rely on cursor TTL: set a bounded cursor timeout so un-closed cursors expire server-side
  4. Retry the close once; closing an already-closed cursor is safe
  5. If persistent, upgrade the elasticsearch-rest-client dependency version

Example fix

// before: assume response exists
Response resp = restClient.performRequest(closeReq);
// after: bound cursor lifetime so cleanup is best-effort
// (set cursor timeout on the query) and retry close
if (!esClient.closeSqlCursor(cursor)) {
    log.info("Cursor close unconfirmed; cursor will expire server-side");
}
Defensive patterns

Strategy: fallback

Try / catch

// cursor close is advisory; rely on cursor TTL if unconfirmed
if (!esClient.closeSqlCursor(cursor)) {
    log.info("SQL cursor close unconfirmed; cursor expires server-side");
}

Prevention

When it happens

Trigger: POST /_sql/close with body {"cursor": ...} returns null from performRequest — abnormal client/wrapper behavior rather than a normal HTTP error.

Common situations: Wrapped/shaded RestClient returning null on transport anomaly; test stubs; gateway dropping the request without a response.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/b7c8aa5ce06d3968. 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:369

     * @param cursor The SQL cursor to close
     * @return True if the cursor was successfully closed
     */
    public boolean closeSqlCursor(String cursor) {
        if (StringUtils.isEmpty(cursor)) {
            log.debug("SQL cursor is empty; skip closing.");
            return false;
        }

        String endpoint = "/_sql/close";
        Request request = new Request("POST", endpoint);
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("cursor", cursor);
        request.setJsonEntity(JsonUtils.toJsonString(requestBody));

        try {
            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;
        }

View on GitHub (pinned to cf67b549a7)