pentaho/pentaho-kettle · error · KettleStepException

DatabaseJoinMeta.Exception.UnableToDetermineQueryFields +…

Error message

DatabaseJoinMeta.Exception.UnableToDetermineQueryFields + Const.CR + sql

What it means

DatabaseJoinMeta.getFields() asks the database for the result layout of the injected SQL (db.getQueryFields, with environment-substituted variables) to append the returned columns to the row; a KettleDatabaseException is rethrown as KettleStepException 'UnableToDetermineQueryFields' plus the SQL. The step needs the query's field metadata to build the output row and cannot proceed without it.

Solutions

  1. Copy the SQL appended in the message (after Const.CR) and run it directly against the database to see the real error.
  2. Fix the SQL syntax or referenced tables/columns in the Database Join dialog.
  3. Ensure all ${VARIABLES} in the SQL are defined (KETTLE variables / environment) before execution.
  4. Verify the step's database connection settings and that the DB is reachable.

Example fix

// before: SQL referencing a renamed table
String sql = "SELECT * FROM cust_old WHERE id = ?";
// after
String sql = "SELECT * FROM customer WHERE id = ?";
Defensive patterns

Strategy: validation

Validate before calling

String resolved = transMeta.environmentSubstitute(meta.getSql());
if (resolved.contains("${")) throw new IllegalArgumentException("Unresolved variables in SQL: " + resolved);
try (PreparedStatement ps = connection.prepareStatement(resolved)) { /* metadata prepared OK */ }

Try / catch

try { transMeta.initializeVariablesFrom(null); }
catch (KettleStepException e) {
  if (e.getMessage().contains("UnableToDetermineQueryFields")) {
    String sql = e.getMessage().substring(e.getMessage().indexOf(Const.CR) + 1);
    log.error("Fix this SQL manually: {}", sql);
  }
}

Prevention

When it happens

Trigger: Transformation initialization or analyseImpact when the SQL is invalid (syntax error, unknown table/columns), the substituted variables produce broken SQL, or the database connection fails while preparing the statement for metadata retrieval.

Common situations: Variable placeholders not set in the run environment; SQL tuned for a different DB dialect; missing table after a schema migration; connection points to the wrong database.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java:296

      return;
    }

    Database db = new Database( loggingObject, databaseMeta );
    databases = new Database[] { db }; // Keep track of this one for cancelQuery

    // Which fields are parameters?
    // info[0] comes from the database connection.
    //
    RowMetaInterface param = getParameterRow( row );

    // First try without connecting to the database... (can be S L O W)
    // See if it's in the cache...
    //
    RowMetaInterface add = null;
    try {
      add = db.getQueryFields( space.environmentSubstitute( sql ), true, param, new Object[param.size()] );
    } catch ( KettleDatabaseException dbe ) {
      throw new KettleStepException( BaseMessages.getString(
        PKG, "DatabaseJoinMeta.Exception.UnableToDetermineQueryFields" )
        + Const.CR + sql, dbe );
    }

    if ( add != null ) { // Cache hit, just return it this...
      for ( int i = 0; i < add.size(); i++ ) {
        ValueMetaInterface v = add.getValueMeta( i );
        v.setOrigin( name );
      }
      row.addRowMeta( add );
    } else {
      // No cache hit, connect to the database, do it the hard way...
      //
      try {
        db.connect();
        add = db.getQueryFields( space.environmentSubstitute( sql ), true, param, new Object[param.size()] );
        for ( int i = 0; i < add.size(); i++ ) {
          ValueMetaInterface v = add.getValueMeta( i );

View on GitHub (pinned to f3058517a1)