pentaho/pentaho-kettle · error · KettleDatabaseException

An error occurred executing SQL:

Error message

An error occurred executing SQL: 

What it means

Thrown by Database.openQuery(...) when a SQLException occurs while executing a SELECT and creating the ResultSet (prepareStatement/executeQuery or reading metadata). The failed SQL is appended after Const.CR. The query result never becomes available.

Solutions

  1. Check the wrapped SQLException cause for the server-side error message
  2. Validate the SQL and referenced table/column names against the target database
  3. Confirm the connection is still alive; reconnect if the query ran long or the network is flaky
  4. Wrap openQuery in try/catch with a fallback query or abort path

Example fix

// before
ResultSet rs = db.openQuery("SELECT id FROM customer WHERE nmae = ?", ...);
// after
ResultSet rs = db.openQuery("SELECT id FROM customer WHERE name = ?", ...);
Defensive patterns

Strategy: try-catch

Validate before calling

if (sql == null || sql.trim().isEmpty()) throw new IllegalArgumentException("Query is empty");

Try / catch

try {
  ResultSet rs = database.openQuery(sql);
} catch (KettleDatabaseException e) {
  Throwable cause = e.getCause();
  logError("openQuery failed for [" + sql + "]: " + (cause != null ? cause.getMessage() : ""), e);
  throw e;
}

Prevention

When it happens

Trigger: Database.openQuery(sql) (and overloads) when executeQuery() or res.getMetaData() throws a SQLException — invalid SQL, table doesn't exist, connection broken, or query cancelled.

Common situations: Table lookup steps pointing at non-existent tables; WHERE clauses with wrong column names; connections dropped during long-running SELECTs; read-only replicas rejecting the query.

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

Appendix: source

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

            selStmt.setFetchSize( fs );
          }
          selStmt.setFetchDirection( fetchMode );
        }
        if ( rowlimit > 0 && databaseMeta.supportsSetMaxRows() ) {
          selStmt.setMaxRows( rowlimit );
        }

        log.snap( Metrics.METRIC_DATABASE_EXECUTE_SQL_START, databaseMeta.getName() );
        res = selStmt.executeQuery( databaseMeta.stripCR( sql ) );
        log.snap( Metrics.METRIC_DATABASE_EXECUTE_SQL_STOP, databaseMeta.getName() );
      }

      // MySQL Hack only. It seems too much for the cursor type of operation on MySQL, to have another cursor opened
      // to get the length of a String field. So, on MySQL, we ignore the length of Strings in result rows.
      //
      rowMeta = getRowInfo( res.getMetaData(), databaseMeta.isMySQLVariant(), lazyConversion );
    } catch ( SQLException ex ) {
      throw new KettleDatabaseException( "An error occurred executing SQL: " + Const.CR + sql, ex );
    } catch ( Exception e ) {
      throw new KettleDatabaseException( "An error occurred executing SQL:" + Const.CR + sql, e );
    } finally {
      log.snap( Metrics.METRIC_DATABASE_OPEN_QUERY_STOP, databaseMeta.getName() );
    }

    return res;
  }

  private boolean canWeSetFetchSize( Statement statement ) throws SQLException {
    return databaseMeta.isFetchSizeSupported()
      && ( statement.getMaxRows() > 0
      || databaseMeta.getDatabaseInterface() instanceof PostgreSQLDatabaseMeta
      || ( databaseMeta.isMySQLVariant() && databaseMeta.isStreamingResults() ) );
  }

  public ResultSet openQuery( PreparedStatement ps, RowMetaInterface params, Object[] data )
    throws KettleDatabaseException {

View on GitHub (pinned to f3058517a1)