pentaho/pentaho-kettle · error · KettleStepException
DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields
Error message
DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields
What it means
DynamicSQLRowMeta.getFields determines the fields returned by the SQL by executing db.getQueryFields(realSQL, false); if that throws KettleDatabaseException it wraps it in a KettleStepException with this message key plus the offending SQL. It signals the step could not infer its output row shape from the database.
Solutions
- Test the SQL template directly against the database (with variables resolved) to see the underlying DB error
- Check DB connection (host, credentials, driver) used by the step
- Fix the SQL so the query fields can be determined (ensure the SELECT list is resolvable)
- Enable variable substitution consistently or fix the variable values in the environment
Example fix
// before
SELECT * FROM ${schema}.orders WHERE dt = '?' // unresolved schema variable
// after
set ${schema} in the run configuration (e.g. schema=public) or hard-code: SELECT * FROM public.orders WHERE dt = ? Defensive patterns
Strategy: try-catch
Validate before calling
// Smoke-test the SQL (with variables resolved) before metadata analysis: Database db = new Database(loggingObject, meta.getDatabaseMeta()); db.connect(); RowMetaInterface fields = db.getQueryFields(space.environmentSubstitute(meta.getSql()), false); db.disconnect();
Try / catch
try {
stepMeta.getStepMetaInterface().getFields(row, origin, info, target, space, repository, metaStore);
} catch (KettleStepException e) {
logError("Could not determine query fields — verify SQL and DB connection", e);
throw e;
} Prevention
- Test SQL templates in a DB client with variables substituted
- Keep DB connections configured and tested in the environment
- Ensure variable substitution settings match the run configuration
- Avoid parameter placeholders that getQueryFields cannot parse
When it happens
Trigger: During metadata analysis (e.g. analyseImpact) or step output-field calculation, when the SQL (after optional environment variable substitution via replacevars) fails to execute or be parsed by the database for field discovery.
Common situations: Invalid SQL template in the step; database unreachable or credentials wrong; variable substitution producing broken SQL; SQL syntax valid at runtime with parameters but not parseable by getQueryFields.
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
- e (no own message; error caching lookup rows)
- Trans.Exception.ErrorInDatabase
- Unable to get queryfields for SQL:
- Unable to load job entry copy from repository with…
- Unable to prepare combi-lookup statement
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/893310ed64925f9c.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRowMeta.java:235
if ( databaseMeta == null ) {
return;
}
Database db = new Database( loggingObject, databaseMeta );
databases = new Database[] { db }; // Keep track of this one for cancelQuery
// First try without connecting to the database... (can be S L O W)
// See if it's in the cache...
RowMetaInterface add = null;
String realSQL = sql;
if ( replacevars ) {
realSQL = space.environmentSubstitute( realSQL );
}
try {
add = db.getQueryFields( realSQL, false );
} catch ( KettleDatabaseException dbe ) {
throw new KettleStepException( BaseMessages.getString(
PKG, "DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields" )
+ Const.CR + sql, dbe );
}
if ( add != null ) { // Cache hit, just return it this...
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( realSQL, false );
for ( int i = 0; i < add.size(); i++ ) {
ValueMetaInterface v = add.getValueMeta( i );
v.setOrigin( name );View on GitHub (pinned to f3058517a1)