NationalSecurityAgency/ghidra · error · ElasticException
Mismatch in decrementVectorCounters
Error message
Mismatch in decrementVectorCounters
What it means
Thrown in decrementVectorCounters when the _id decoded from a bulk update response item does not match the expected vector id from the iterator. Elasticsearch's bulk API guarantees responses are returned in the same order as requests; a mismatch indicates a protocol contract violation, response body corruption, or a desynchronization between the two parallel iterators (iter1 for building requests, iter2 for matching responses).
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/elastic/ElasticDatabase.java:1828
buffer.append("\"_id\": \"");
Base64Lite.encodeLongBase64(buffer, entry.id);
buffer.append("\", \"retry_on_conflict\": 5 } }\n");
buffer.append(
"{ \"script\": { \"inline\": \"if ((ctx._source.count -= params.count) <=0) { ctx.op = \\\"delete\\\" }\", ");
buffer.append("\"params\": { \"count\": ").append(entry.count).append("} } }\n");
}
JsonObject resp = connection.executeBulk("/_bulk", buffer.toString());
JsonArray items = (JsonArray) resp.get("items");
for (int i = 0; i < maxVectors; ++i) {
if (!iter2.hasNext()) {
break;
}
IdHistogram entry = iter2.next();
JsonObject item = (JsonObject) items.get(i);
JsonObject update = (JsonObject) item.get("update");
long id = Base64Lite.decodeLongBase64(update.get("_id").getAsString());
if (id != entry.id) {
throw new ElasticException("Mismatch in decrementVectorCounters");
}
if ("deleted".equals(ElasticConnection.convertToString(update.get("result")))) {
deleteList.add(entry); // Mark this vector for full deletion
}
}
}
/**
* Delete vector documents in bulk. This assumes multiplicity counts in the "meta" documents
* have already been checked, and these vectors are scheduled for full document deletion.
* Vectors are presented as an iterator to IdHistograms. One bulk deletion request is
* submitted containing vectors up to a given maximum number. The iterator is advanced by
* the number submitted
* @param iter is an iterator over records containing the id's to delete
* @param maxVectors is the maximum number to delete for this window
* @throws ElasticException for communication problems with the server
*/
private void deleteRawVectors(Iterator<IdHistogram> iter, int maxVectors)View on GitHub (pinned to d5f144c24d)
Solutions
- Report as a bug — this guard should never fire with a compliant Elasticsearch server; investigate proxy or load-balancer interference with bulk NDJSON responses.
- Verify that the two iterators (iter1, iter2) passed to decrementVectorCounters point to the same underlying list and are at the same position.
- Check for any HTTP intermediary (reverse proxy, API gateway) that might buffer or reorder bulk responses.
- Confirm the Elasticsearch server version adheres to the standard bulk response ordering contract.
Defensive patterns
Strategy: try-catch
Try / catch
try {
database.query(query);
} catch (ElasticException e) {
if (e.getMessage().contains("Mismatch in decrementVectorCounters")) {
// Should never occur — indicates protocol violation or proxy interference
Msg.error(this, "Bulk response order mismatch — check proxy/load-balancer: " + e.getMessage());
}
throw e;
} Prevention
- Ensure no HTTP proxy or load balancer reorders or buffers bulk NDJSON responses.
- Verify the two iterators passed to decrementVectorCounters are backed by the same list.
- Use a direct connection to Elasticsearch for bulk operations, bypassing any intermediary.
When it happens
Trigger: During executable deletion, decrementVectorCounters sends a bulk update to repository_meta with retry_on_conflict=5, then iterates the response items alongside iter2. Base64Lite.decodeLongBase64(update.get("_id").getAsString()) for item i is compared against entry.id from iter2; any difference triggers the exception.
Common situations: Should never occur under normal operation. If seen, it points to: a proxy or load balancer reordering or corrupting bulk response items; a bug in how iter1 and iter2 are managed by the caller; an Elasticsearch bulk API contract violation in a non-standard server fork.
Related errors
- Error during vector deletion
- Unknown error format
- {getType()}scripts cannot be used for context [{context.name
- Unknown script name {scriptSource}
- Document is missing "features"
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/e9df2612482da68b.
Report an issue: GitHub.