NationalSecurityAgency/ghidra · error · LSHException

Optional table does not exist when it should:

Error message

Optional table does not exist when it should: 

What it means

Thrown by TableScoreCaching during threshold re-initialization when QueryOptionalExist reports the optional score table does not exist (response.tableExists is false) even though clearTable=true was requested. This is an internal consistency failure: the code assumed the optional table was already created but the database does not contain it. It indicates the database was never fully initialized or the optional table was dropped externally.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/TableScoreCaching.java:211

	}

	@Override
	public void resetStorage(double simThresh, double sigThresh) throws LSHException {
		simThreshold = simThresh;
		sigThreshold = sigThresh;
		cacheMap = new TreeMap<String, Float>();				// Clear the cache
		QueryOptionalExist query = new QueryOptionalExist();
		query.tableName = TABLE_NAME;
		query.keyType = Types.VARCHAR;
		query.valueType = Types.REAL;
		query.attemptCreation = false;
		query.clearTable = true;								// Clear out the table
		ResponseOptionalExist response = query.execute(db);
		if (response == null) {
			throw new LSHException(db.getLastError().message);
		}
		if (!response.tableExists) {
			throw new LSHException("Optional table does not exist when it should: " + TABLE_NAME);
		}
		setUpInsert(2);
		insertValue.keys[0] = SIMILARITY_KEY;
		insertValue.keys[1] = SIGNIFICANCE_KEY;
		insertValue.values[0] = Float.valueOf((float) simThreshold);		// Write thresholds to special table rows
		insertValue.values[1] = Float.valueOf((float) sigThreshold);
		if (insertValue.execute(db) == null) {
			throw new LSHException("Unable to initialize new thresholds: " + TABLE_NAME);
		}
	}

}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Run the full BSim database initialization that creates all optional tables (use the creation path with attemptCreation=true) before setting thresholds.
  2. Upgrade the database schema to the current BSim version so all optional tables exist.
  3. Check database version metadata and re-create the database if the optional table is missing.
  4. Avoid manually dropping BSim internal tables; use the supported admin/maintenance commands.
Defensive patterns

Strategy: validation

Validate before calling

// Check the database has the optional score table before initializing thresholds.
boolean hasOptionalTable = bsimDatabase.hasOptionalTable(TableScoreCaching.TABLE_NAME);
if (!hasOptionalTable) {
    bsimDatabase.initializeOptionalTables(); // full creation path with attemptCreation=true
}

Try / catch

try {
    scoreCaching.setThresholds(sim, sig);
} catch (LSHException e) {
    if (e.getMessage().contains("Optional table does not exist")) {
        bsimDatabase.initializeOptionalTables();
        scoreCaching.setThresholds(sim, sig); // retry after creation
    } else throw e;
}

Prevention

When it happens

Trigger: Calling the threshold-reset/initialize path on a TableScoreCaching whose backing SQL BSim database lacks the optional score table. Triggered when setThresholds() or equivalent is invoked before the table has ever been created, or after a manual DROP of the optional table. The query sets attemptCreation=false, so it will not auto-create.

Common situations: Database created with an older BSim schema version that did not include the optional score table. Manual schema surgery that removed the table. A fresh database that was never initialized via the full creation path (which would set attemptCreation=true). Version mismatch between BSim client and the on-disk database schema.

Related errors


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