apache/seatunnel · warning · ElasticsearchConnectorException

DELETE_PIT_FAILED

DELETE_PIT_FAILED

Error message

DELETE /_pit response null

What it means

deletePointInTime closes a PIT context (DELETE /_pit with the pit id in the body); if performRequest returns null the client throws DELETE_PIT_FAILED. This happens at the end of a read; a null response means the cleanup request never got an HTTP answer, potentially leaving the PIT open on the server until keep_alive expires.

Source

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

        }
    }

    /**
     * Deletes a Point-in-Time (PIT).
     *
     * @param pitId The PIT ID to delete
     * @return True if the PIT was successfully deleted
     */
    public boolean deletePointInTime(String pitId) {
        String endpoint = "/_pit";
        Request request = new Request("DELETE", endpoint);
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("id", pitId);
        request.setJsonEntity(JsonUtils.toJsonString(requestBody));
        try {
            Response response = restClient.performRequest(request);
            if (response == null) {
                throw new ElasticsearchConnectorException(
                        ElasticsearchConnectorErrorCode.DELETE_PIT_FAILED,
                        "DELETE " + endpoint + " response null");
            }
            String entity = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                JsonNode jsonNode = JsonUtils.parseObject(entity);
                return jsonNode.get("succeeded").asBoolean();
            } else {
                throw new ElasticsearchConnectorException(
                        ElasticsearchConnectorErrorCode.DELETE_PIT_FAILED,
                        String.format(
                                "DELETE %s response status code=%d, body=%s",
                                endpoint, response.getStatusLine().getStatusCode(), entity));
            }
        } catch (IOException ex) {
            throw new ElasticsearchConnectorException(
                    ElasticsearchConnectorErrorCode.DELETE_PIT_FAILED, ex);
        }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Ignore-and-retry is usually safe: the PIT auto-expires after keep_alive, so rerunning rarely causes resource exhaustion
  2. Check cluster for lingering PITs (GET /_nodes/stats) and wait for expiry or restart node if leaking
  3. Verify network stability for long-running jobs (idle TCP timeouts on LBs); tune keep-alive/TCP settings
  4. Fix any custom client wrapper that can return null instead of throwing
Defensive patterns

Strategy: fallback

Validate before calling

// ensure the PIT id is present before cleanup
if (pitId == null || pitId.isEmpty()) { skipDelete(); }

Type guard

if (pitId == null || pitId.isEmpty()) { return; } // nothing to delete

Try / catch

try {
    esRestClient.deletePointInTime(pitId);
} catch (ElasticsearchConnectorException e) {
    // cleanup is best-effort: log WARN, PIT expires via keep_alive
    log.warn("PIT cleanup failed, will expire via keep_alive", e);
}

Prevention

When it happens

Trigger: DELETE /_pit (body: {"id":"<pitId>"}) returning null Response from performRequest.

Common situations: Custom/mock RestClient returning null; connection already broken after a long read so the DELETE cannot be delivered; proxy dropping idle connections mid-job.

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/c6f89451f662829f. Report an issue: GitHub.