pentaho/pentaho-kettle · error · KettleStepException

Unable to get queryfields for SQL:

Error message

Unable to get queryfields for SQL: 

What it means

In TableInputMeta.getFields() (impact-analysis path), the library previews the step's SQL via db.getQueryFields(sNewSQL, param) to derive the output row fields. When the database engine/driver rejects the SQL (KettleDatabaseException), it is wrapped in KettleStepException with message 'Unable to get queryfields for SQL: ' plus the SQL text.

Solutions

  1. Validate the step's SQL directly (Preview / SQL editor) — the exception message contains the full failing SQL.
  2. Resolve Kettle variables before analysis or set default values for ${var} placeholders.
  3. Test the database connection used by the step.
  4. If the SQL uses parameters (?), ensure they are supported in this path or restructure the query so getQueryFields can infer columns.
  5. Check the wrapped KettleDatabaseException cause for the driver's specific error.

Example fix

// before: unresolved variable breaks query-field inference
meta.setSQL("SELECT * FROM ${TABLE_NAME}");
// after: ensure the variable is defined before analyseImpact runs
transMeta.setVariable("TABLE_NAME", "customers");
meta.setSQL("SELECT * FROM ${TABLE_NAME}");
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: check connection and resolve variables before getFields/analyseImpact
if (!databaseMeta.testConnectionSuccess()) throw new IllegalStateException("DB connection fails");
String resolved = transMeta.environmentSubstitute(meta.getSQL());
if (resolved.contains("${")) throw new IllegalStateException("Unresolved variables in SQL: " + resolved);

Try / catch

try {
  meta.getFields(row, origin, info, target, databaseMeta, metaStore);
} catch (KettleStepException e) {
  log.error("Query field inference failed for SQL: " + e.getMessage() + ", cause: " + KettleUtil.getMessage(e));
}

Prevention

When it happens

Trigger: analyseImpact -> getFields executes the SQL through Database.getQueryFields and the query fails: SQL syntax error, invalid variables (SQL with ${...} not yet substituted), connection failure, or schema/table referenced by the SQL does not exist.

Common situations: SQL containing unresolved Kettle variables or ?-parameters that getQueryFields cannot bind; typo in table/column names; database unreachable during impact analysis; dialect-specific SQL the driver's preview cannot parse.

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/c5082b3a4c9c3b7c. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/tableinput/TableInputMeta.java:233

    boolean param = false;

    Database db = getDatabase();
    super.databases = new Database[] { db }; // keep track of it for canceling purposes...

    // First try without connecting to the database... (can be S L O W)
    String sNewSQL = sql;
    if ( isVariableReplacementActive() ) {
      sNewSQL = db.environmentSubstitute( sql );
      if ( space != null ) {
        sNewSQL = space.environmentSubstitute( sNewSQL );
      }
    }

    RowMetaInterface add = null;
    try {
      add = db.getQueryFields( sNewSQL, param );
    } catch ( KettleDatabaseException dbe ) {
      throw new KettleStepException( "Unable to get queryfields for SQL: " + Const.CR + sNewSQL, dbe );
    }

    if ( add != null ) {
      attachOrigin( add, origin );
      row.addRowMeta( add );
    } else {
      try {
        db.connect();

        RowMetaInterface paramRowMeta = null;
        Object[] paramData = null;

        StreamInterface infoStream = getStepIOMeta().getInfoStreams().get( 0 );
        if ( !Utils.isEmpty( infoStream.getStepname() ) ) {
          param = true;
          if ( info.length > 0 && info[ 0 ] != null ) {
            paramRowMeta = info[ 0 ];
            paramData = RowDataUtil.allocateRowData( paramRowMeta.size() );

View on GitHub (pinned to f3058517a1)