pentaho/pentaho-kettle · error · KettleDatabaseException

Couldn't prepare statement:

Error message

Couldn't prepare statement:

What it means

KettleDatabaseException thrown when Connection.prepareStatement(sql) fails, wrapping the SQLException and including the offending SQL in the message. Means the driver rejected the SQL at prepare time — typically syntax errors, unknown tables/columns, or a closed connection.

Solutions

  1. Read the SQL printed in the message and run it manually in the DB to see the precise syntax error
  2. Verify the table/column names and schema exist and are correctly quoted/cased
  3. Confirm the connection is still open; reconnect if it was closed
  4. Adapt SQL to the target database dialect

Example fix

// before
String sql = "INSERT INTO usr (id,name) VALUES (?, ?)"; // table is actually 'users'
database.prepareInsert(rowMeta, schema, "usr");
// after
String sql = "INSERT INTO users (id,name) VALUES (?, ?)";
database.prepareInsert(rowMeta, schema, "users");
Defensive patterns

Strategy: try-catch

Validate before calling

if ( database.getConnection() == null || database.getConnection().isClosed() ) {
  database.connect();
}

Type guard

boolean canPrepare( Database db ) throws SQLException {
  Connection c = db.getConnection();
  return c != null && !c.isClosed();
}

Try / catch

try {
  database.prepareInsert( rowMeta, schema, table );
} catch ( KettleDatabaseException e ) {
  log.error( "Prepare failed for SQL: " + e.getMessage() );
  throw e;
}

Prevention

When it happens

Trigger: Calling prepareSQL/prepareInsert/lookup paths where connection.prepareStatement() throws SQLException — invalid SQL syntax, referenced table/column does not exist, connection closed, or parameter count unsupported.

Common situations: Typo in table/column names, SQL built dynamically with wrong placeholders, missing schema, DB dialect differences (SQL valid in one engine, not another), or stale closed connection.

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

Appendix: source

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

   * Prepare a statement to be executed on the database.
   *
   * @param sql        The SQL to be prepared
   * @param returnKeys set to true if you want to return generated keys from an insert statement
   * @return The PreparedStatement object.
   * @throws KettleDatabaseException
   */
  public PreparedStatement prepareSQL( String sql, boolean returnKeys ) throws KettleDatabaseException {
    DatabaseInterface databaseInterface = databaseMeta.getDatabaseInterface();
    boolean supportsAutoGeneratedKeys = databaseInterface.supportsAutoGeneratedKeys();

    try {
      if ( returnKeys && supportsAutoGeneratedKeys ) {
        return connection.prepareStatement( databaseMeta.stripCR( sql ), Statement.RETURN_GENERATED_KEYS );
      } else {
        return connection.prepareStatement( databaseMeta.stripCR( sql ) );
      }
    } catch ( SQLException ex ) {
      throw new KettleDatabaseException( "Couldn't prepare statement:" + Const.CR + sql, ex );
    }
  }

  public void closeLookup() throws KettleDatabaseException {
    if ( pstmt != null ) {
      closePreparedStatement( pstmt );
      pstmt = null;
    }
  }

  public void closePreparedStatement( PreparedStatement ps ) throws KettleDatabaseException {
    if ( ps != null ) {
      try {
        ps.close();
      } catch ( SQLException e ) {
        throw new KettleDatabaseException( "Error closing prepared statement", e );
      }
    }

View on GitHub (pinned to f3058517a1)