pentaho/pentaho-kettle · error · KettleDatabaseException

Unable to prepare statement for SQL statement [

Error message

Unable to prepare statement for SQL statement [

What it means

setLookup failed to prepare the JDBC PreparedStatement used for the lookup (SELECT ... WHERE key fields) against the target table. SQLExceptions from connection.prepareStatement are wrapped in a KettleDatabaseException including the SQL text.

Solutions

  1. Click SQL on the step to see/execute the generated SQL; create the missing table or fix column names.
  2. Verify Schema/Table names and key column names in the step settings.
  3. Test the database connection (wrong host/db/driver produces prepare failures).
  4. Check the wrapped SQLException cause in the log for the real database error (permissions, syntax, missing object).

Example fix

// before: table name typo causes prepare failure
meta.setTableName("custmor");
// after
meta.setTableName("customer"); // existing table in schema
Defensive patterns

Strategy: try-catch

Validate before calling

// before running, ensure the lookup table exists
Database db = new Database(transMeta, meta.getDatabaseMeta());
db.connect();
if (!db.checkTableExists(schema, table))
  throw new IllegalStateException("Lookup table missing: " + table);

Type guard

null

Try / catch

try { trans.execute(...); } catch (KettleDatabaseException e) {
  if (e.getMessage().startsWith("Unable to prepare statement")) {
    Throwable sqlEx = e.getCause(); // inspect real SQLException
  }
  throw e;
}

Prevention

When it happens

Trigger: Invalid SQL generated from step metadata (bad table/column names, wrong quoting), or the JDBC driver/database cannot prepare the statement (missing table, permission denied, unsupported syntax, bad connection).

Common situations: Target table doesn't exist yet; reserved word used as a column without quoting; wrong schema name; wrong or outdated JDBC driver; connection pointing 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/1aa65358825d9303. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/insertupdate/InsertUpdate.java:392

          data.lookupParameterRowMeta.addValueMeta(
            rowMeta.searchValueMeta( meta.getKeyFields()[ i ].getKeyStream() ).clone() );

        } else {
          sql += " " + meta.getKeyFields()[ i ].getKeyCondition() + " ? ";
          data.lookupParameterRowMeta.addValueMeta(
            rowMeta.searchValueMeta( meta.getKeyFields()[ i ].getKeyStream() ) );
        }
      }
      sql += " ) ) ";
    }

    try {
      if ( log.isDetailed() ) {
        logDetailed( "Setting preparedStatement to [" + sql + "]" );
      }
      data.prepStatementLookup = data.db.getConnection().prepareStatement( databaseMeta.stripCR( sql ) );
    } catch ( SQLException ex ) {
      throw new KettleDatabaseException( "Unable to prepare statement for SQL statement [" + sql + "]", ex );
    }
  }

  // Lookup certain fields in a table
  public void prepareUpdate( RowMetaInterface rowMeta ) throws KettleDatabaseException {
    DatabaseMeta databaseMeta = meta.getDatabaseMeta();
    data.updateParameterRowMeta = new RowMeta();

    String sql = "UPDATE " + data.schemaTable + Const.CR;
    sql += "SET ";

    boolean comma = false;

    for ( int i = 0; i < meta.getUpdateFields().length; i++ ) {
      if ( meta.getUpdateFields()[ i ].getUpdate().booleanValue() ) {
        if ( comma ) {
          sql += ",   ";
        } else {

View on GitHub (pinned to f3058517a1)