NationalSecurityAgency/ghidra · error · SQLException

{}

Error message

{}

What it means

Thrown as an SQLException wrapping an IOException by H2VectorTable.readVectors() when restoring a vector from its Base64-encoded representation fails. The readVectors() method iterates all rows in h2_vectable and calls vectorFactory.restoreVectorFromBase64() for each; an IOException here means the stored Base64 vector data is malformed or cannot be decoded into a valid LSHVector.

Source

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

	 * @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)) {
			while (rs.next()) {
				long id = rs.getLong(1);
				int count = rs.getInt(2);
				Reader r = new StringReader(rs.getString(3));
				LSHVector vec = vectorFactory.restoreVectorFromBase64(r, vectorDecodeBuffer);
				VectorStoreEntry entry =
					new VectorStoreEntry(id, vec, count, vectorFactory.getSelfSignificance(vec));
				map.put(id, entry);
			}
		}
		catch (IOException e) {
			throw new SQLException(e); // unexpected for StringReader
		}
		return map;
	}

	/**
	 * Get vector details which correspond to specified vector ID
	 * @param id vector ID
	 * @return vector details
	 * @throws SQLException if error occurs
	 */
	public VectorResult queryVectorById(long id) throws SQLException {

		VectorStoreEntry entry = vectorStore.getVectorById(id);
		if (entry != null) {
			return new VectorResult(id, entry.count(), 0, 0, entry.vec());
		}

		PreparedStatement s = select_by_rowid_stmt.prepareIfNeeded(

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Identify which vector row(s) have corrupt data by querying the table and attempting decode row-by-row.
  2. If the encoding format changed between versions, rebuild the database with the current Ghidra version.
  3. Check for H2 database file corruption and run H2 recovery tools.
  4. If only a few rows are affected, delete the corrupt vectors and re-insert them from the source program.

Example fix

// before
try {
    return vectorTable.readVectors();
} catch (SQLException e) {
    // opaque wrapping of IOException
}

// after (identify the bad row)
Map<Long, VectorStoreEntry> map = new HashMap<>();
try (Statement st = db.createStatement();
        ResultSet rs = st.executeQuery("SELECT id,count,vec FROM " + TABLE_NAME)) {
    while (rs.next()) {
        long id = rs.getLong(1);
        try {
            LSHVector vec = vectorFactory.restoreVectorFromBase64(
                new StringReader(rs.getString(3)), buf);
            map.put(id, new VectorStoreEntry(id, vec, rs.getInt(2), 0));
        } catch (IOException e) {
            Msg.warn(this, "Skipping corrupt vector id=" + id);
        }
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify vector data is decodable for a sample before full read
try (Statement st = db.createStatement();
        ResultSet rs = st.executeQuery("SELECT id,vec FROM " + TABLE_NAME + " LIMIT 1")) {
    if (rs.next()) {
        vectorFactory.restoreVectorFromBase64(
            new StringReader(rs.getString(2)), buf);
    }
}

Try / catch

try {
    return vectorTable.readVectors();
} catch (SQLException e) {
    if (e.getCause() instanceof IOException) {
        // One or more vectors have corrupt data
        // Read row-by-row, skipping corrupt entries
        return readVectorsTolerant(vectorTable);
    }
    throw e;
}

Prevention

When it happens

Trigger: Occurs when restoreVectorFromBase64() throws IOException for any row during the full table scan. This happens when: the vec column contains truncated or corrupted Base64 data, a character encoding mismatch occurred during storage, the vector factory version changed and cannot decode the old format, or the CLOB data was partially overwritten.

Common situations: Database was created with an older Ghidra/BSim version whose vector encoding format differs. File-level corruption of the H2 database. The CLOB column was truncated due to storage limits. A failed or partial database migration altered vector data.

Related errors


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