NationalSecurityAgency/ghidra · error · ElasticException

Error sending request:

Error message

Error sending request: 

What it means

IOException handler inside executeBulk. Bulk requests send large application/x-ndjson bodies, so beyond the usual connect/DNS/TLS failures this commonly fires on write-side problems: connection reset while streaming a big body, or a proxy rejecting/aborting an oversized POST.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/elastic/ElasticConnection.java:377

			connection = (HttpURLConnection) httpURL.openConnection();
			connection.setRequestMethod(POST);
			connection.setRequestProperty("Content-Type", "application/x-ndjson");
			connection.setDoOutput(true);
			try (Writer writer = new OutputStreamWriter(connection.getOutputStream())) {
				writer.write(body);
			}
			lastResponseCode = connection.getResponseCode();
			JsonObject resp = grabResponse(connection);
			if (!lastRequestSuccessful()) {
				throw new ElasticException(parseErrorJSON(resp));
			}
			return resp;
		}
		catch (URISyntaxException e) {
			throw new ElasticException("Error parsing URL: " + e.getMessage());
		}
		catch (IOException e) {
			throw new ElasticException("Error sending request: " + e.getMessage());
		}
		catch (JsonParseException e) {
			throw new ElasticException("Error parsing response: " + e.getMessage());
		}
		finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
	}

	public JsonObject executeURIOnly(String command, String path) throws ElasticException {
		HttpURLConnection connection = null;
		try {
			URL httpURL = new URI(httpURLbase + path).toURL();
			connection = (HttpURLConnection) httpURL.openConnection();
			connection.setRequestMethod(command);
			connection.setDoOutput(true);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Reduce the bulk batch size (number of action/source pairs per executeBulk call) so each POST fits proxy limits and completes before idle timeouts.
  2. Classify by subtype: ConnectException -> ES down/wrong port; SocketTimeoutException -> raise timeout / shrink batch; SSLHandshakeException -> fix truststore.
  3. Retry the failed batch with backoff; bulk operations are not atomic so de-dup on re-run if your action has an id.

Example fix

// before
c.executeBulk("_bulk", wholeNdjson);
// after
for (String chunk : splitNdjson(wholeNdjson, 1000)) {
    retryTransient(() -> c.executeBulk("_bulk", chunk), 3);
}
Defensive patterns

Strategy: retry

Validate before calling

public static List<String> chunked(String ndjson, int pairsPerChunk) {
    // split NDJSON into bounded chunks so each POST fits proxy limits
    List<String> out = new ArrayList<>(); StringBuilder b = new StringBuilder(); int n = 0;
    for (String line : ndjson.split("\n")) { b.append(line).append('\n'); if ((++n & 1) == 0 && n/2 >= pairsPerChunk) { out.add(b.toString()); b.setLength(0); } }
    if (b.length() > 0) out.add(b.toString());
    return out;
}

Try / catch

for (String chunk : chunked(ndjson, 1000)) {
    for (int attempt = 0; ; attempt++) {
        try { conn.executeBulk("_bulk", chunk); break; }
        catch (ElasticException e) {
            if (!e.getMessage().startsWith("Error sending request") || attempt == 3) throw e;
            Thread.sleep(500L << attempt);
        }
    }
}

Prevention

When it happens

Trigger: Socket failure while opening the connection or streaming the NDJSON body; getResponseCode/read failure; reset on a very large bulk POST; proxy client_max_body_size or timeout aborting the request; null error stream in grabResponse.

Common situations: Bulk-ingesting many vectors at once against an ES behind a proxy with a small body limit; ES still starting; network flakiness during long bulk writes; TLS misconfig on https ES.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/c65632dbb3bdc77a. Report an issue: GitHub.