NationalSecurityAgency/ghidra · critical · ElasticException

Mismatch in vectorid

Error message

Mismatch in vectorid

What it means

Internal consistency check in fetchVectors: after a vector/_mget multi-get, each returned document's base64 _id is decoded and compared to VectorResult.vectorid at the same position. A mismatch means the returned docs are not in the requested order/id. ES _mget preserves order, so this points at a reordering proxy/gateway, a non-ES backend, a plugin, or index corruption.

Source

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

			buffer.append(", \"");
			Base64Lite.encodeLongBase64(buffer, vecRes.vectorid);
			buffer.append('\"');
		}
		buffer.append(" ] }");
		JsonObject resp =
			connection.executeStatement(ElasticConnection.GET, "vector/_mget", buffer.toString());
		JsonArray docs = (JsonArray) resp.get("docs");
		char[] vectorDecodeBuffer = Base64VectorFactory.allocateBuffer();
		for (int i = 0; i < maxDocuments; ++i) {
			if (!iter2.hasNext()) {
				break;
			}
			vecRes = iter2.next();
			JsonObject oneResp = (JsonObject) docs.get(i);
			String matchId = oneResp.get("_id").getAsString();
			long matchIdVal = Base64Lite.decodeLongBase64(matchId);
			if (matchIdVal != vecRes.vectorid) {
				throw new ElasticException("Mismatch in vectorid");
			}
			JsonElement source = oneResp.get("_source");
			if (ElasticConnection.isNull(source)) {
				throw new ElasticException("vector document does not exist for id=" + matchId);
			}
			StringReader reader =
				new StringReader(((JsonObject) source).get("features").getAsString());
			try {
				vecRes.vec = vectorFactory.restoreVectorFromBase64(reader, vectorDecodeBuffer);
			}
			catch (IOException e) {
				throw new ElasticException(e.getMessage());
			}
		}
	}

	/**
	 * Given a list of FunctionDescriptions, fill in the matching SignatureRecords

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Reproduce with a direct curl vector/_mget bypassing the proxy to confirm ES preserves order.
  2. Re-run in smaller batches, or match docs to VectorResults by id rather than position when post-processing.
  3. If corruption is confirmed, reindex the BSim vector index from a known-good source.

Example fix

// before: positional trust of _mget order (internal to fetchVectors)
// after (defensive wrapper)
try { db.fetchVectors(it1, it2, n); }
catch (ElasticException e) { if (e.getMessage().equals("Mismatch in vectorid")) { db.fetchVectors(it1copy, it2copy, n); return; } throw e; }
Defensive patterns

Strategy: fallback

Validate before calling

// Internal ordering assertion; mitigate by verifying _mget order directly.
public static boolean vectorMgetOrdered(String url) throws Exception {
    HttpURLConnection h = (HttpURLConnection) URI.create(url + "/vector/_mget").toURL().openConnection();
    h.setRequestMethod("GET"); h.setDoOutput(true);
    try (Writer w = new OutputStreamWriter(h.getOutputStream())) { w.write("{\"ids\":[\"AAAB\",\"AAAC\"]}"); }
    JsonObject r = JsonParser.parseReader(new InputStreamReader(h.getInputStream())).getAsJsonObject();
    return ((JsonArray) r.get("docs")).get(0).getAsJsonObject().get("_id").getAsString().equals("AAAB");
}

Try / catch

try {
    db.fetchVectors(it1, it2, n);
} catch (ElasticException e) {
    if (!e.getMessage().equals("Mismatch in vectorid")) throw e;
    fetchVectorsSingly(it1, n); // order-independent single gets
}

Prevention

When it happens

Trigger: fetchVectors reading docs[i] whose decoded _id != the i-th vectorid. Caused by a proxy rewriting multi-get responses, an OpenSearch/plugin variant, or corruption returning wrong ids for the vector index.

Common situations: ES behind a gateway that reorders _mget; talking to a non-standard ES fork; rare corruption after replication fault.

Related errors


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