NationalSecurityAgency/ghidra · error · SQLException

Bad vector table rowid

Error message

Bad vector table rowid

What it means

Thrown as an SQLException by H2FileFunctionDatabase.queryVectorId() when vectorTable.queryVectorById(id) returns null. This indicates the requested vector ID does not correspond to any row in the h2_vectable, meaning a stale or invalid vector ID was passed to the query layer.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/H2FileFunctionDatabase.java:208

			passwordChangeRequest.passwordResponse.changeSuccessful = false;
			passwordChangeRequest.passwordResponse.errorMessage =
				"Unsupported operation for H2 backend";
		}
		else if (query instanceof AdjustVectorIndex q) {
			q.buildResponseTemplate();
			q.adjustresponse.operationSupported = false;
		}
		else {
			return super.doQuery(query, c);
		}
		return query.getResponse();
	}

	@Override
	protected VectorResult queryVectorId(long id) throws SQLException {
		VectorResult rowres = vectorTable.queryVectorById(id);
		if (rowres == null) {
			throw new SQLException("Bad vector table rowid");
		}
		return rowres;
	}

	@Override
	protected long storeSignatureRecord(SignatureRecord sigrec) throws SQLException {
		// NOTE: ignore sigrec count - assume only one (1)
		return vectorTable.updateVector(sigrec.getLSHVector(), 1);
	}

	@Override
	protected int queryNearestVector(List<VectorResult> resultset, LSHVector vec, double simthresh,
			double sigthresh, int max) throws SQLException {
		VectorCompare comp;
		List<VectorResult> resultsToSort = new ArrayList<>();
		for (VectorStoreEntry entry : vectorStore) {
			if (entry.selfSig() < sigthresh) {
				continue;

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Check for concurrent modifications to the database — ensure no other process is deleting vectors during queries.
  2. If the vector ID comes from a cached result, refresh the cache from the database.
  3. If the database was rebuilt, re-run the query from scratch rather than using stale IDs.
  4. Run readVectorMap() to verify which vector IDs currently exist and compare with the failing ID.

Example fix

// before
VectorResult res = db.queryVectorId(staleId); // throws

// after
Map<Long, VectorStoreEntry> validIds = db.readVectorMap();
if (!validIds.containsKey(staleId)) {
    // ID is stale; skip or re-query
    return null;
}
VectorResult res = db.queryVectorId(staleId);
Defensive patterns

Strategy: validation

Validate before calling

// Verify vector ID exists before querying
Map<Long, VectorStoreEntry> validIds = database.readVectorMap();
if (!validIds.containsKey(vectorId)) {
    throw new IllegalArgumentException(
        "Vector ID " + vectorId + " does not exist in the database");
}

Try / catch

try {
    VectorResult result = database.queryVectorId(id);
} catch (SQLException e) {
    if (e.getMessage().equals("Bad vector table rowid")) {
        // ID is stale or invalid; handle gracefully
        Msg.warn(this, "Vector ID " + id + " not found; skipping");
        return null;
    }
    throw e;
}

Prevention

When it happens

Trigger: Occurs when queryVectorId() is called (typically during query resolution that resolves functions to their vectors) with an ID that has no matching row. This can happen when: the vector was deleted between query construction and execution, the ID came from a stale cache, or there is a data integrity issue where a function/description references a vector ID that doesn't exist.

Common situations: Concurrent modification of the database (one thread deletes vectors while another queries). Using a cached vector ID after the database was rebuilt. Data corruption or partial database migration. Race condition between insert and query in a multi-threaded context.

Related errors


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