pentaho/pentaho-kettle · error · KettleDatabaseException

ERROR executing query

Error message

ERROR executing query

What it means

Thrown by Database.openQuery(...) variants that fetch row layout via getRowInfo(res.getMetaData(), ...) — the query itself succeeded, but extracting the ResultSetMetaData / building the RowMetaInterface failed. Message 'ERROR executing query' with the exception as cause.

Solutions

  1. Inspect the cause stack trace to see which metadata call failed
  2. Update the JDBC driver to a version with correct ResultSetMetaData support
  3. Avoid lazy conversion or unusual column types if the driver cannot describe them
  4. Check that the result set is read immediately after openQuery, before any timeout closes it
Defensive patterns

Strategy: try-catch

Validate before calling

if (database.getConnection() == null) throw new IllegalStateException("No connection for query metadata");

Try / catch

try {
  ResultSet rs = database.openQuery(sql);
  RowMetaInterface rm = database.getReturnRowMeta();
} catch (KettleDatabaseException e) {
  logError("Failed reading row metadata for query", e);
  throw e;
}

Prevention

When it happens

Trigger: Database.getRows/openQuery paths that call getRowInfo(...) when the JDBC metadata access throws — e.g. driver returns null or invalid metadata, or the result set was already closed/consumed.

Common situations: Buggy or too-old JDBC drivers with incomplete ResultSetMetaData support; result set closed by timeout before metadata is read; exotic column types the driver cannot describe.

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

Appendix: source

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

      if ( rowlimit > 0 && databaseMeta.supportsSetMaxRows() ) {
        ps.setMaxRows( rowlimit );
      }

      log.snap( Metrics.METRIC_DATABASE_EXECUTE_SQL_START, databaseMeta.getName() );
      res = ps.executeQuery();
      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.
      //
      log.snap( Metrics.METRIC_DATABASE_GET_ROW_META_START, databaseMeta.getName() );
      rowMeta = getRowInfo( res.getMetaData(), databaseMeta.isMySQLVariant(), false );
      log.snap( Metrics.METRIC_DATABASE_GET_ROW_META_STOP, databaseMeta.getName() );
    } catch ( Exception e ) {
      throw new KettleDatabaseException( "ERROR executing query", e );
    } finally {
      log.snap( Metrics.METRIC_DATABASE_OPEN_QUERY_STOP, databaseMeta.getName() );
    }

    return res;
  }

  void setMysqlFetchSize( PreparedStatement ps, int fs, int getMaxRows ) throws SQLException, KettleDatabaseException {
    if ( databaseMeta.isStreamingResults() && getDatabaseMetaData().getDriverMajorVersion() == 3 ) {
      ps.setFetchSize( Integer.MIN_VALUE );
    } else if ( fs <= getMaxRows ) {
      // PDI-11373 do not set fetch size more than max rows can returns
      ps.setFetchSize( fs );
    }
  }

  /**
   * Returns a RowMeta describing the fields of a table expression.

View on GitHub (pinned to f3058517a1)