{"record":{"id":"b7c8aa5ce06d3968","repo":"apache/seatunnel","slug":"post-response-null-for-cursor","errorCode":null,"errorMessage":"POST {} response null for cursor: {}","messagePattern":"POST (.+?) response null for cursor: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java","lineNumber":369,"sourceCode":"     * @param cursor The SQL cursor to close\n     * @return True if the cursor was successfully closed\n     */\n    public boolean closeSqlCursor(String cursor) {\n        if (StringUtils.isEmpty(cursor)) {\n            log.debug(\"SQL cursor is empty; skip closing.\");\n            return false;\n        }\n\n        String endpoint = \"/_sql/close\";\n        Request request = new Request(\"POST\", endpoint);\n        Map<String, String> requestBody = new HashMap<>();\n        requestBody.put(\"cursor\", cursor);\n        request.setJsonEntity(JsonUtils.toJsonString(requestBody));\n\n        try {\n            Response response = restClient.performRequest(request);\n            if (response == null) {\n                log.warn(\"POST {} response null for cursor: {}\", endpoint, cursor);\n                return false;\n            }\n            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {\n                String entity = EntityUtils.toString(response.getEntity());\n                JsonNode jsonNode = JsonUtils.parseObject(entity);\n                return jsonNode.get(\"succeeded\").asBoolean();\n            } else {\n                log.warn(\n                        \"POST {} response status code={} for cursor: {}\",\n                        endpoint,\n                        response.getStatusLine().getStatusCode(),\n                        cursor);\n                return false;\n            }\n        } catch (Exception ex) {\n            log.warn(\"Failed to close SQL cursor: {}\", cursor, ex);\n            return false;\n        }","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java#L351-L387","documentation":"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.","triggerScenarios":"POST /_sql/close with body {\"cursor\": ...} returns null from performRequest — abnormal client/wrapper behavior rather than a normal HTTP error.","commonSituations":"Wrapped/shaded RestClient returning null on transport anomaly; test stubs; gateway dropping the request without a response.","solutions":["Verify Elasticsearch connectivity and any proxy in front of it that could swallow requests","Check whether a custom RestClient wrapper returns null instead of throwing; fix the wrapper to surface transport exceptions","Rely on cursor TTL: set a bounded cursor timeout so un-closed cursors expire server-side","Retry the close once; closing an already-closed cursor is safe","If persistent, upgrade the elasticsearch-rest-client dependency version"],"exampleFix":"// before: assume response exists\nResponse resp = restClient.performRequest(closeReq);\n// after: bound cursor lifetime so cleanup is best-effort\n// (set cursor timeout on the query) and retry close\nif (!esClient.closeSqlCursor(cursor)) {\n    log.info(\"Cursor close unconfirmed; cursor will expire server-side\");\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// cursor close is advisory; rely on cursor TTL if unconfirmed\nif (!esClient.closeSqlCursor(cursor)) {\n    log.info(\"SQL cursor close unconfirmed; cursor expires server-side\");\n}","preventionTips":["Set a bounded cursor timeout on SQL queries","Check for wrappers that can return null from performRequest","Close cursors while the REST client is still open","Treat cursor cleanup as non-fatal; alert on recurrence instead"],"tags":["elasticsearch","sql-cursor","null-response","http"],"backgroundTag":"http-request-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}