pentaho/pentaho-kettle · error · KettleDatabaseException

Unable to get database meta-data from the database.

Error message

Unable to get database meta-data from the database.

What it means

Thrown by the private Database.getTableMetaData(schema, table) when connection.getMetaData() returns null, meaning no usable JDBC DatabaseMetaData is available — usually because there is no open connection. It is a precondition guard before querying table descriptions.

Solutions

  1. Call database.connect() before any API that inspects table metadata
  2. Verify the connection was not closed earlier in the flow (disconnect in finally too early)
  3. Check connection.isOpened()/getDatabaseMetaData() != null before invoking metadata-dependent APIs
  4. Obtain a fresh Database/Connection instance if a previous error invalidated it

Example fix

// before
Database db = new Database(meta);
RowMetaInterface f = db.getTableFields("t"); // metadata null
// after
Database db = new Database(meta);
db.connect();
RowMetaInterface f = db.getTableFields("t");
Defensive patterns

Strategy: type-guard

Validate before calling

if (!database.isOpened() || database.getDatabaseMetaData() == null) {
  throw new IllegalStateException("Database metadata unavailable - connect first");
}

Type guard

boolean hasDbMeta(Database database) {
  return database != null && database.isOpened() && database.getDatabaseMetaData() != null;
}

Try / catch

if (!hasDbMeta(database)) {
  database.connect();
}
try {
  RowMetaInterface fields = database.getTableFields(table);
} catch (KettleDatabaseException e) {
  logError("getTableMetaData failed - check connection state", e);
  throw e;
}

Prevention

When it happens

Trigger: Calling Database.getTableMetaData indirectly (e.g. getTableFields/getDDL for a table) while the database connection has not been opened or was closed, so getDatabaseMetaData() == null.

Common situations: Steps calling table-field lookups on a Database instance whose connect() was never called or whose disconnect() ran earlier; connections invalidated by a previous fatal SQLException.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/d4e0960eb66d24e0. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:2251

      throw new KettleDatabaseException(
        BaseMessages.getString( PKG, "Database.Error.UnableToCheckExistingTable", tablename, databaseMeta.getName() ),
        e );
    }
    return isTableExist;
  }

  /**
   * Retrieves the table description matching the schema and table name.
   *
   * @param schema the schema name pattern
   * @param table  the table name pattern
   * @return table description row set
   * @throws KettleDatabaseException if DatabaseMetaData is null or some database error occurs
   */
  private ResultSet getTableMetaData( String schema, String table ) throws KettleDatabaseException {
    ResultSet tables = null;
    if ( getDatabaseMetaData() == null ) {
      throw new KettleDatabaseException( BaseMessages.getString( PKG, "Database.Error.UnableToGetDbMeta" ) );
    }
    try {
      tables = databaseMeta.getTables(
        getDatabaseMetaData(), schema, table, TABLE_TYPES_TO_GET );
    } catch ( SQLException e ) {
      throw new KettleDatabaseException( BaseMessages.getString( PKG, "Database.Error.UnableToGetTableNames" ), e );
    }
    if ( tables == null ) {
      throw new KettleDatabaseException( BaseMessages.getString( PKG, "Database.Error.UnableToGetTableNames" ) );
    }
    return tables;
  }

  /**
   * Retrieves the columns metadata matching the schema and table name.
   *
   * @param schema the schema name pattern
   * @param table  the table name pattern

View on GitHub (pinned to f3058517a1)