NationalSecurityAgency/ghidra · critical · SQLException

Could not create database:

Error message

Could not create database: 

What it means

During BSim database creation, several DDL statements build the core tables (exeCategory, exe, desc, callgraph when tracked) plus install weights and IDF lookups. Any SQLException from these steps is caught and re-wrapped into a single `new SQLException("Could not create database: " + err.getMessage())`. The original message text is preserved, but the SQL state and cause chain are flattened into the string, which can hamper root-cause analysis.

Source

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

				commit = true;
			}
			finally {
				endTransaction(commit);
			}

			exeCategoryTable.create(st);
			exeTable.create(st);
			descTable.create(st);

			if (trackcallgraph) {
				callgraphTable.create(st);
			}

			installWeights(db, config.weightfactory);
			installIDFLookup(db, config.idflookup);
		}
		catch (final SQLException err) {
			throw new SQLException("Could not create database: " + err.getMessage());
		}
	}

	/**
	 * Drop this database
	 * @throws SQLException if a database error occured
	 */
	abstract protected void dropDatabase() throws SQLException;

	protected void setConnectionOnTables(Connection db) {

		weightTable.setConnection(db);
		idfLookupTable.setConnection(db);

		archtable.setConnection(db);
		compilertable.setConnection(db);
		repositorytable.setConnection(db);
		pathtable.setConnection(db);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Read the appended original message after 'Could not create database:' for the true SQL error (privilege, duplicate object, etc.).
  2. Verify the DB user has CREATE on the target database and that the schema is empty or pre-seeded correctly.
  3. Drop conflicting tables or point at a fresh, dedicated database.
  4. Confirm the JDBC URL and driver match the configured BSim flavor.

Example fix

# before: targeting a populated / under-privileged db
jdbc:postgresql://host/already_used_db
# after: fresh dedicated db with granted privileges
jdbc:postgresql://host/fresh_bsim_db   # role has CREATE
Defensive patterns

Strategy: try-catch

Validate before calling

// Before createDatabase: verify role can create tables and schema is clean.
try (Connection c = ds.getConnection(); Statement s = c.createStatement()) {
    ResultSet rs = s.executeQuery(
        "SELECT has_database_privilege(current_database(),'CREATE')");
    rs.next();
    if (!rs.getBoolean(1)) throw new IllegalStateException("role lacks CREATE privilege");
    // ensure no conflicting tables already exist
    rs = s.executeQuery("SELECT count(*) FROM information_schema.tables " +
        "WHERE table_schema='public'");
    rs.next();
    if (rs.getInt(1) > 0) throw new IllegalStateException("schema not empty");
}

Try / catch

try {
    db.createDatabase();
} catch (SQLException e) {
    // the wrapped message carries the root SQL error text
    String root = e.getMessage().substring("Could not create database: ".length());
    log.error("DB creation failed, root cause: {}", root);
    throw e; // abort setup; do not retry unchanged
}

Prevention

When it happens

Trigger: Calling the database-create path when the DB role lacks CREATE TABLE privileges, target tables already exist with an incompatible shape, the connection drops mid-DDL, or disk/quota is exhausted. Any of these surfaces as the wrapped message.

Common situations: First-time setup with an under-privileged role; pointing BSim at a database name that already holds unrelated or older-schema tables; H2-vs-PostgreSQL driver mismatch; wrong JDBC URL; restoring onto a DB with leftover objects.

Related errors


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