{"record":{"id":"893310ed64925f9c","repo":"pentaho/pentaho-kettle","slug":"dynamicsqlrowmeta-exception-unabletodeterminequeryfields","errorCode":null,"errorMessage":"DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields","messagePattern":"DynamicSQLRowMeta\\.Exception\\.UnableToDetermineQueryFields","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRowMeta.java","lineNumber":235,"sourceCode":"\n    if ( databaseMeta == null ) {\n      return;\n    }\n\n    Database db = new Database( loggingObject, databaseMeta );\n    databases = new Database[] { db }; // Keep track of this one for cancelQuery\n\n    // First try without connecting to the database... (can be S L O W)\n    // See if it's in the cache...\n    RowMetaInterface add = null;\n    String realSQL = sql;\n    if ( replacevars ) {\n      realSQL = space.environmentSubstitute( realSQL );\n    }\n    try {\n      add = db.getQueryFields( realSQL, false );\n    } catch ( KettleDatabaseException dbe ) {\n      throw new KettleStepException( BaseMessages.getString(\n        PKG, \"DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields\" )\n        + Const.CR + sql, dbe );\n    }\n\n    if ( add != null ) { // Cache hit, just return it this...\n      for ( int i = 0; i < add.size(); i++ ) {\n        ValueMetaInterface v = add.getValueMeta( i );\n        v.setOrigin( name );\n      }\n      row.addRowMeta( add );\n    } else {\n      // No cache hit, connect to the database, do it the hard way...\n      try {\n        db.connect();\n        add = db.getQueryFields( realSQL, false );\n        for ( int i = 0; i < add.size(); i++ ) {\n          ValueMetaInterface v = add.getValueMeta( i );\n          v.setOrigin( name );","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRowMeta.java#L217-L253","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nSELECT * FROM ${schema}.orders WHERE dt = '?'   // unresolved schema variable\n// after\nset ${schema} in the run configuration (e.g. schema=public) or hard-code: SELECT * FROM public.orders WHERE dt = ?","handlingStrategy":"try-catch","validationCode":"// Smoke-test the SQL (with variables resolved) before metadata analysis:\nDatabase db = new Database(loggingObject, meta.getDatabaseMeta());\ndb.connect();\nRowMetaInterface fields = db.getQueryFields(space.environmentSubstitute(meta.getSql()), false);\ndb.disconnect();","typeGuard":null,"tryCatchPattern":"try {\n  stepMeta.getStepMetaInterface().getFields(row, origin, info, target, space, repository, metaStore);\n} catch (KettleStepException e) {\n  logError(\"Could not determine query fields — verify SQL and DB connection\", e);\n  throw e;\n}","preventionTips":["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"],"tags":["kettle","sql","database"],"backgroundTag":"sql-query-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}