apache/seatunnel · error · ElasticsearchConnectorException
BULK_RESPONSE_ERROR
BULK_RESPONSE_ERROR
Error message
bulk es Response is null
What it means
EsRestClient.bulk sends a POST /_bulk request and expects an HTTP Response object. If restClient.performRequest returns null (no response object at all), it throws ElasticsearchConnectorException with code BULK_RESPONSE_ERROR. This guards downstream NPEs when reading status code and entity from the response.
Source
Thrown at seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/client/EsRestClient.java:129
for (int i = 0; i < hosts.size(); i++) {
httpHosts[i] = HttpHost.create(hosts.get(i));
}
return RestClient.builder(httpHosts)
.setRequestConfigCallback(
requestConfigBuilder ->
requestConfigBuilder
.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT));
}
public BulkResponse bulk(String requestBody) {
Request request = new Request("POST", "/_bulk");
request.setJsonEntity(requestBody);
try {
Response response = restClient.performRequest(request);
if (response == null) {
throw new ElasticsearchConnectorException(
ElasticsearchConnectorErrorCode.BULK_RESPONSE_ERROR,
"bulk es Response is null");
}
String entity = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
JsonNode json = OBJECT_MAPPER.readTree(entity);
int took = json.get("took").asInt();
boolean errors = json.get("errors").asBoolean();
return new BulkResponse(errors, took, entity);
} else {
throw new ElasticsearchConnectorException(
ElasticsearchConnectorErrorCode.BULK_RESPONSE_ERROR,
String.format(
"bulk es response status=%s, response body=%s, request body(truncate)=%s",
response.getStatusLine().getStatusCode(),
entity,
requestBody.substring(0, Math.min(1000, requestBody.length()))));
}View on GitHub (pinned to cf67b549a7)
Solutions
- Verify Elasticsearch is reachable and the RestClient host/port/credentials are correct
- Check network path (LB/proxy idle timeouts) and keep-alive settings; retry the bulk request
- Catch ElasticsearchConnectorException with code BULK_RESPONSE_ERROR in the writer and retry with backoff
- Upgrade/inspect the low-level RestClient setup; ensure no wrapper layer can return null
Example fix
// before
BulkResponse resp = esRestClient.bulk(requestBody);
// after
try {
BulkResponse resp = esRestClient.bulk(requestBody);
} catch (ElasticsearchConnectorException e) {
if (ElasticsearchConnectorErrorCode.BULK_RESPONSE_ERROR.equals(e.getErrorCode())) {
retryBulk(requestBody);
} else { throw e; }
} Defensive patterns
Strategy: retry
Validate before calling
boolean clientHealthy = esRestClient != null; // verify via a lightweight HEAD / ping before bulking
Try / catch
try { client.bulk(body); } catch (ElasticsearchConnectorException e) { if (BULK_RESPONSE_ERROR.equals(e.getErrorCode())) retryWithBackoff(body); else throw e; } Prevention
- Keep connections alive and tune RestClient timeouts
- Monitor cluster health before and during bulk writes
- Avoid proxies that can drop the response without status
When it happens
Trigger: POST /_bulk returning a null Response object from the low-level RestClient — normally caused by an abnormal connection state (connection closed, client misconfigured, or a mocked/failed transport) rather than a normal HTTP error.
Common situations: Broken or half-closed HTTP connections to Elasticsearch during bulk writes; RestClient misconfiguration (bad host list) causing performRequest to yield null in a wrapper; a proxy or load balancer silently terminating the request; unit/test harnesses returning null responses.
Related errors
- BULK_RESPONSE_ERROR
- SCROLL_REQUEST_ERROR
- GET_INDEX_DOCS_COUNT_FAILED
- LIST_INDEX_FAILED
- CREATE_INDEX_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/465a30cae65dcc3b.
Report an issue: GitHub.