pentaho/pentaho-kettle · error · KettleDatabaseException

MySQLDatabaseMeta.Exception.LegacyColumnNameException

MySQLDatabaseMeta.Exception.LegacyColumnNameException

Error message

%s: %s (localized message + e.getMessage())

What it means

Wraps any Exception from reading the column name/label (getColumnLabel or getColumnName, chosen by driver major version > 3) in MySQLDatabaseMeta.getLegacyColumnName. The message combines the localized 'LegacyColumnNameException' text with the underlying exception's message, keeping the cause chained.

Solutions

  1. Validate index against rsMetaData.getColumnCount() (1-based) before the call
  2. Keep the ResultSet open until all columns are processed
  3. Inspect the chained cause in the KettleDatabaseException for the driver-level error

Example fix

// before
for (int i = 0; i < rsMetaData.getColumnCount(); i++) {
  String name = meta.getLegacyColumnName(dbMetaData, rsMetaData, i);
}
// after
for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
  String name = meta.getLegacyColumnName(dbMetaData, rsMetaData, i);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (index < 1 || index > rsMetaData.getColumnCount()) throw new IllegalArgumentException("Column index " + index + " out of 1.." + rsMetaData.getColumnCount());

Type guard

function isValidColumnIndex(ResultSetMetaData md, int i) { try { return i >= 1 && i <= md.getColumnCount(); } catch (SQLException e) { return false; } }

Try / catch

try {
  String name = mysqlMeta.getLegacyColumnName(dbMetaData, rsMetaData, index);
} catch (KettleDatabaseException e) {
  Throwable cause = e.getCause(); // underlying SQLException from getColumnLabel/getColumnName
  log.error("Failed to read MySQL column name for index " + index + ": " + (cause != null ? cause.getMessage() : e.getMessage()), e);
}

Prevention

When it happens

Trigger: ResultSetMetaData.getColumnLabel(index) or getColumnName(index) throws — typically an invalid index (out of 1..columnCount range) or a closed/stale ResultSet.

Common situations: Off-by-one column loops; accessing metadata after closing the statement; MySQL Connector/J errors during metadata retrieval.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/a180fe6877d3614c. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/MySQLDatabaseMeta.java:535

   * @param dbMetaData
   * @param rsMetaData
   * @param index
   * @return The column label if version is greater than 3 or the column name if version is lower or equal to 3.
   * @throws KettleDatabaseException
   */
  public String getLegacyColumnName( DatabaseMetaData dbMetaData, ResultSetMetaData rsMetaData, int index ) throws KettleDatabaseException {
    if ( dbMetaData == null ) {
      throw new KettleDatabaseException( BaseMessages.getString( PKG, "MySQLDatabaseMeta.Exception.LegacyColumnNameNoDBMetaDataException" ) );
    }

    if ( rsMetaData == null ) {
      throw new KettleDatabaseException( BaseMessages.getString( PKG, "MySQLDatabaseMeta.Exception.LegacyColumnNameNoRSMetaDataException" ) );
    }

    try {
      return dbMetaData.getDriverMajorVersion() > 3 ? rsMetaData.getColumnLabel( index ) : rsMetaData.getColumnName( index );
    } catch ( Exception e ) {
      throw new KettleDatabaseException( String.format( "%s: %s", BaseMessages.getString( PKG, "MySQLDatabaseMeta.Exception.LegacyColumnNameException" ), e.getMessage() ), e );
    }
  }
}

View on GitHub (pinned to f3058517a1)