pentaho/pentaho-kettle · error · KettleDatabaseException

An error occurred executing SQL:

Error message

An error occurred executing SQL:

What it means

The non-SQLException twin of the previous error in Database.openQuery(...): any Exception other than SQLException while opening the query throws this message (note the missing space before the SQL in this variant). It signals an unexpected internal/driver failure rather than a rejected statement.

Solutions

  1. Inspect the cause stack trace for the real exception
  2. Ensure the database connection is open before calling openQuery
  3. Update the JDBC driver and Pentaho/Kettle version to compatible levels
Defensive patterns

Strategy: try-catch

Validate before calling

if (!database.isOpened()) throw new IllegalStateException("Connection not open for openQuery");

Try / catch

try {
  ResultSet rs = database.openQuery(sql);
} catch (KettleDatabaseException e) {
  logError("openQuery unexpected failure on [" + sql + "]", e); // message omits space; log SQL yourself
  throw e;
}

Prevention

When it happens

Trigger: Database.openQuery(sql) when a RuntimeException or other non-SQL exception occurs — e.g. null connection, driver class cast errors, memory issues building row metadata.

Common situations: Calling openQuery without an open connection; incompatible JDBC driver versions throwing unexpected runtime exceptions; Kettle lazy-conversion bugs.

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

Appendix: source

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

          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 {
    ResultSet res;

View on GitHub (pinned to f3058517a1)