NationalSecurityAgency/ghidra · error · SQLException

Unable to obtain vector id for insert

Error message

Unable to obtain vector id for insert

What it means

Thrown as an SQLException by H2VectorTable.insert() when getGeneratedKeys() returns an empty ResultSet after a successful INSERT. The insert reported 1 affected row, but the H2 driver did not provide a generated key, leaving the new vector's auto-generated ID unavailable.

Source

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

		LSHVector vec = (LSHVector) arguments[1];

		PreparedStatement s = insert_stmt.prepareIfNeeded(() -> db.prepareStatement(
			"INSERT INTO " + TABLE_NAME + " (count,vec_hash,vec) VALUES(?,?,?)",
			Statement.RETURN_GENERATED_KEYS));

		StringBuilder vecBuf = new StringBuilder();
		vec.saveBase64(vecBuf, Base64Lite.encode);

		s.setInt(1, count);
		s.setLong(2, vec.calcUniqueHash());
		s.setString(3, vecBuf.toString());
		if (s.executeUpdate() != 1) {
			throw new SQLException("Insert failed for vector table");
		}
		long id;
		try (ResultSet rs = s.getGeneratedKeys()) {
			if (!rs.next()) {
				throw new SQLException("Unable to obtain vector id for insert");
			}
			id = rs.getLong(1);
		}
		vectorStore.update(
			new VectorStoreEntry(id, vec, count, vectorFactory.getSelfSignificance(vec)));
		return id;
	}

	/**
	 * Read all vectors from table and generate an ID-based vector map
	 * @return vector map (ID->VectorStoreEntry)
	 * @throws SQLException if error occurs
	 */
	public Map<Long, VectorStoreEntry> readVectors() throws SQLException {
		char[] vectorDecodeBuffer = Base64VectorFactory.allocateBuffer();
		HashMap<Long, VectorStoreEntry> map = new HashMap<>();
		try (Statement st = db.createStatement();
				ResultSet rs = st.executeQuery("SELECT id,count,vec FROM " + TABLE_NAME)) {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Verify the H2 JDBC driver version matches what Ghidra bundles/expects.
  2. Check that the PreparedStatement was created with Statement.RETURN_GENERATED_KEYS (it is in the current code).
  3. If the issue persists, query the last inserted ID via an alternative method (e.g., IDENTITY() or SELECT MAX(id)).
  4. Rebuild the database if the schema or driver was changed mid-stream.

Example fix

// before
try (ResultSet rs = s.getGeneratedKeys()) {
    if (!rs.next()) {
        throw new SQLException("Unable to obtain vector id for insert");
    }
    id = rs.getLong(1);
}

// after (fallback: query by vec_hash to get the assigned id)
try (ResultSet rs = s.getGeneratedKeys()) {
    if (rs.next()) {
        id = rs.getLong(1);
    } else {
        try (PreparedStatement q = db.prepareStatement(
                "SELECT id FROM " + TABLE_NAME + " WHERE vec_hash = ?")) {
            q.setLong(1, vec.calcUniqueHash());
            try (ResultSet qr = q.executeQuery()) {
                qr.next();
                id = qr.getLong(1);
            }
        }
    }
}
Defensive patterns

Strategy: fallback

Try / catch

long id;
try (ResultSet rs = s.getGeneratedKeys()) {
    if (rs.next()) {
        id = rs.getLong(1);
    } else {
        // Fallback: retrieve ID via the unique vec_hash
        try (PreparedStatement q = db.prepareStatement(
                "SELECT id FROM " + TABLE_NAME + " WHERE vec_hash = ?")) {
            q.setLong(1, vec.calcUniqueHash());
            try (ResultSet qr = q.executeQuery()) {
                if (!qr.next()) throw new SQLException("Vector insert succeeded but ID unrecoverable");
                id = qr.getLong(1);
            }
        }
    }
}

Prevention

When it happens

Trigger: Occurs when the INSERT succeeded (returned 1) but Statement.getGeneratedKeys() yields no rows. This happens when: the PreparedStatement was not created with RETURN_GENERATED_KEYS properly, the H2 driver version doesn't support generated keys for the SERIAL/CLOB combination, or there is a driver-level bug in key retrieval.

Common situations: H2 JDBC driver version incompatibility with Ghidra's BSim module. The SERIAL PRIMARY KEY column doesn't properly report generated keys in certain H2 modes. H2 running in a compatibility mode (e.g., PostgreSQL emulation) that alters generated key behavior.

Related errors


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