pentaho/pentaho-kettle · error · KettleStepException
DatabaseJoinMeta.Exception.ErrorObtainingFields
Error message
DatabaseJoinMeta.Exception.ErrorObtainingFields
What it means
In DatabaseJoinMeta.getFields(), after successfully obtaining the query field row metadata, the code copies fields, sets origins, closes the DB, and wraps any KettleDatabaseException raised in that block as KettleStepException 'DatabaseJoinMeta.Exception.ErrorObtainingFields'. Unlike error 1318, the query metadata was fetched but the post-processing/cleanup of the connection or row copy failed.
Solutions
- Check the chained cause dbe for the concrete JDBC failure during the field-copy/close phase.
- Test the database connection and network stability; re-run the transformation.
- Avoid sharing the Database object across threads; get a fresh connection per call.
- Update the JDBC driver if the stack trace points at driver-level close/connection errors.
Example fix
// before: shared Database reused after close elsewhere
db.close();
// after: ensure single-owner lifecycle
if (db != null && !db.isClosed()) { db.close(); } Defensive patterns
Strategy: retry
Validate before calling
try (Connection c = dataSource.getConnection()) {
if (!c.isValid(5)) throw new IllegalStateException("DB connection invalid before getFields");
} Try / catch
int attempts = 0;
while (attempts < 3) {
try { meta.getFields(...); break; }
catch (KettleStepException e) {
if (!e.getMessage().contains("ErrorObtainingFields") || ++attempts == 3) throw e;
Thread.sleep(1000L * attempts); // retry on transient connection loss
}
} Prevention
- Keep DB connections idle-timeout free during initialization
- Avoid sharing Database objects across threads
- Keep JDBC drivers current for stable connection close behavior
When it happens
Trigger: getFields when db.close() or the row-copy/setOrigin loop throws a KettleDatabaseException — typically a connection failure during close, or an already-closed/broken connection in the cached query-fields path.
Common situations: Database connection dropped between getQueryFields and close (network timeout, DB restart); connection pool invalidation; a connection object shared across threads being closed twice.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- DynamicSQLRowMeta.Exception.ErrorObtainingFields
- LucidDBStreamingLoaderMeta.Exception.ConnectionNotDefined
- LucidDBStreamingLoaderMeta.Exception.ErrorGettingFields
- SynchronizeAfterMergeMeta.Exception.ConnectionNotDefined
- Trans.Exception.ErrorConnectingToDatabase
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/d5ec0f7ca788fb3b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java:320
for ( int i = 0; i < add.size(); i++ ) {
ValueMetaInterface v = add.getValueMeta( i );
v.setOrigin( name );
}
row.addRowMeta( add );
} else {
// No cache hit, connect to the database, do it the hard way...
//
try {
db.connect();
add = db.getQueryFields( space.environmentSubstitute( sql ), true, param, new Object[param.size()] );
for ( int i = 0; i < add.size(); i++ ) {
ValueMetaInterface v = add.getValueMeta( i );
v.setOrigin( name );
}
row.addRowMeta( add );
db.close();
} catch ( KettleDatabaseException dbe ) {
throw new KettleStepException( BaseMessages.getString(
PKG, "DatabaseJoinMeta.Exception.ErrorObtainingFields" ), dbe );
}
}
}
@Override
public String getXML() {
StringBuilder retval = new StringBuilder( 300 );
retval
.append( " " ).append(
XMLHandler.addTagValue( "connection", databaseMeta == null ? "" : databaseMeta.getName() ) );
retval.append( " " ).append( XMLHandler.addTagValue( "rowlimit", rowLimit ) );
retval.append( " " ).append( XMLHandler.addTagValue( "sql", sql ) );
retval.append( " " ).append( XMLHandler.addTagValue( "outer_join", outerJoin ) );
retval.append( " " ).append( XMLHandler.addTagValue( "replace_vars", replacevars ) );
retval.append( " <parameter>" ).append( Const.CR );
for ( int i = 0; i < parameterField.length; i++ ) {View on GitHub (pinned to f3058517a1)