NationalSecurityAgency/ghidra · error · SQLException
Optional table: column type mismatch
Error message
Optional table: column type mismatch
What it means
BSim supports optional metadata tables (extra key/value tables). `getOptionalTable` searches existing optional tables by name; if one is found whose key or value column types differ from the requested `keyType`/`valueType`, it throws SQLException. This refuses to silently read data under a mismatched schema.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/AbstractSQLFunctionDatabase.java:772
* Establish an optional key/value table with this connection.
* The OptionalTable object is created and added to the list for this connection.
* If the caller desires, the table is tested for existence. If it doesn't
* exist, the object is not added to the list and null is returned.
* @param tableName is the name of the SQL table
* @param keyType is the type-code of the key column
* @param valueType is the type-code of the value column
* @param testExistence if true, we test the existence of the table
* @return the OptionalTable or null
* @throws SQLException for problems with the connection, or if
* the table exists with different column types
*/
private OptionalTable getOptionalTable(String tableName, int keyType, int valueType,
boolean testExistence) throws SQLException {
if (optionaltables != null) { // Search for existing table
for (OptionalTable table : optionaltables) {
if (table.getName().equals(tableName)) {
if (keyType != table.getKeyType() || valueType != table.getValueType()) {
throw new SQLException("Optional table: column type mismatch");
}
return table;
}
}
}
// If we reach here, table object doesn't exist, so we create it
OptionalTable table = new OptionalTable(tableName, keyType, valueType, db);
if (testExistence) { // If the user requested
if (!table.exists()) { // test for the existence of the table
table.close();
return null; // If it doesn't exist, don't save new table object, return null
}
}
// Insert the new table object at the end of the list
OptionalTable[] newArray;
if (optionaltables != null) {
newArray = Arrays.copyOf(optionaltables, optionaltables.length + 1);
newArray[optionaltables.length] = table;View on GitHub (pinned to d5f144c24d)
Solutions
- Drop the offending optional table and let BSim recreate it with the correct types.
- Align client and server BSim versions so both expect the same schema.
- Re-run the official BSim migration tooling to normalize the schema.
- If data must be preserved, export, drop, recreate, and re-import.
Defensive patterns
Strategy: validation
Validate before calling
// Before requesting an optional table, verify its column types match expectations.
String sql = "SELECT column_name, data_type FROM information_schema.columns " +
"WHERE table_name = ? ORDER BY ordinal_position";
try (Connection c = ds.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, tableName);
ResultSet rs = ps.executeQuery();
// compare returned types against the keyType/valueType you intend to request
} Try / catch
try {
OptionalTable t = db.getOptionalTable(name, keyType, valueType, true);
} catch (SQLException e) {
if (e.getMessage().equals("Optional table: column type mismatch")) {
// schema incompatibility -- align versions or recreate the table
throw new SchemaIncompatibleException(name, e);
}
throw e;
} Prevention
- Keep BSim client and server versions in lockstep.
- Run official migrations before accessing optional tables.
- Never ALTER optional tables manually; let BSim own their schema.
- Treat a type mismatch as a version-skew smell and audit the deployment.
When it happens
Trigger: A database created under one BSim version defined an optional table with certain column types; a later access requests the same table name with different types -- e.g. after an incomplete schema migration or with mixed client/server versions.
Common situations: Version skew between BSim client and server; a manual ALTER TABLE on an optional table; partial/aborted migration; two deployments sharing one DB with divergent schemas.
Related errors
- Optional table does not exist when it should:
- {}
- Column {} is not indexed
- Cannot find column '{}' for @DBAnnotatedColumn on {}
- DBAnnotatedObject {objectType} must have @DBAnnotatedObjectI
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/16ac94a0e9c6c7fa.
Report an issue: GitHub.