NationalSecurityAgency/ghidra · error · SQLException

Database already exists: {}

Error message

Database already exists: {}

What it means

Thrown as an SQLException by H2FileFunctionDatabase.generateRawDatabase() when the H2 file data source already exists on disk. This method is called during database creation and expects to start from scratch, so an existing file is treated as an error to prevent silent data loss or corruption.

Source

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

	protected void setConnectionOnTables(Connection db) {
		vectorTable.setConnection(db);
		super.setConnectionOnTables(db);
	}

	@Override
	protected Connection initConnection() throws SQLException {
		if (getStatus() != Status.Ready && !fileDs.exists()) {
			throw new SQLException(
				"Database does not exist: " + fileDs.getServerInfo().getDBName());
		}
		return super.initConnection();
	}

	@Override
	protected void generateRawDatabase() throws SQLException {
		BSimServerInfo serverInfo = fileDs.getServerInfo();
		if (fileDs.exists()) {
			throw new SQLException("Database already exists: " + serverInfo.getDBName());
		}
		try (Connection c = fileDs.getConnection()) {
			// do nothing - should throw exception on error
		}
	}

	@Override
	protected void createDatabase(Configuration config) throws SQLException {
		try {
			super.createDatabase(config);

			Connection db = initConnection();
			try (Statement st = db.createStatement()) {
				vectorTable.create(st);
			}
		}
		catch (final SQLException err) {
			throw new SQLException("Could not create database: " + err.getMessage());

View on GitHub (pinned to d5f144c24d)

Solutions

  1. If the existing database is stale or unwanted, drop it first using dropDatabase() or delete the file manually.
  2. If the existing database is valid, connect to it instead of creating a new one (use the read/connect path rather than generateRawDatabase).
  3. Use a different database name/path for the new database.
  4. Add a pre-creation check: if fileDs.exists(), skip or prompt the user.

Example fix

// before
db.generateRawDatabase(); // throws if file exists

// after
if (fileDs.exists()) {
    if (overwrite) {
        db.dropDatabase();
    } else {
        throw new IllegalStateException("Database exists, use overwrite=true or different name");
    }
}
db.generateRawDatabase();
Defensive patterns

Strategy: validation

Validate before calling

// Check if database exists before attempting creation
if (fileDs.exists()) {
    if (overwriteAllowed) {
        database.dropDatabase();
    } else {
        throw new IllegalStateException(
            "Database already exists: " + serverInfo.getDBName() +
            ". Use overwrite=true to replace.");
    }
}

Try / catch

try {
    database.generateRawDatabase();
} catch (SQLException e) {
    if (e.getMessage().startsWith("Database already exists:")) {
        // Decide: drop and recreate, or use existing
        if (overwrite) {
            database.dropDatabase();
            database.generateRawDatabase();
        }
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Occurs when createDatabase/generateRawDatabase is called for an H2 URL whose target file already exists. This happens when: running a 'create' command on a database name that's already been created, re-running a BSim database generation script without first dropping the old database, or pointing two create operations at the same file.

Common situations: Running a BSim 'generate' headless command on a file that was previously generated. Scripting a database creation pipeline without checking for existing output. Accidentally reusing a database name from a prior run.

Related errors


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