{"record":{"id":"079198cb7fe50c0c","repo":"pentaho/pentaho-kettle","slug":"databasejoinmeta-exception-unabletodeterminequeryfields","errorCode":null,"errorMessage":"DatabaseJoinMeta.Exception.UnableToDetermineQueryFields + Const.CR + sql","messagePattern":"DatabaseJoinMeta\\.Exception\\.UnableToDetermineQueryFields \\+ Const\\.CR \\+ sql","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java","lineNumber":296,"sourceCode":"      return;\n    }\n\n    Database db = new Database( loggingObject, databaseMeta );\n    databases = new Database[] { db }; // Keep track of this one for cancelQuery\n\n    // Which fields are parameters?\n    // info[0] comes from the database connection.\n    //\n    RowMetaInterface param = getParameterRow( row );\n\n    // First try without connecting to the database... (can be S L O W)\n    // See if it's in the cache...\n    //\n    RowMetaInterface add = null;\n    try {\n      add = db.getQueryFields( space.environmentSubstitute( sql ), true, param, new Object[param.size()] );\n    } catch ( KettleDatabaseException dbe ) {\n      throw new KettleStepException( BaseMessages.getString(\n        PKG, \"DatabaseJoinMeta.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      //\n      try {\n        db.connect();\n        add = db.getQueryFields( space.environmentSubstitute( sql ), true, param, new Object[param.size()] );\n        for ( int i = 0; i < add.size(); i++ ) {\n          ValueMetaInterface v = add.getValueMeta( i );","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java#L278-L314","documentation":"DatabaseJoinMeta.getFields() asks the database for the result layout of the injected SQL (db.getQueryFields, with environment-substituted variables) to append the returned columns to the row; a KettleDatabaseException is rethrown as KettleStepException 'UnableToDetermineQueryFields' plus the SQL. The step needs the query's field metadata to build the output row and cannot proceed without it.","triggerScenarios":"Transformation initialization or analyseImpact when the SQL is invalid (syntax error, unknown table/columns), the substituted variables produce broken SQL, or the database connection fails while preparing the statement for metadata retrieval.","commonSituations":"Variable placeholders not set in the run environment; SQL tuned for a different DB dialect; missing table after a schema migration; connection points to the wrong database.","solutions":["Copy the SQL appended in the message (after Const.CR) and run it directly against the database to see the real error.","Fix the SQL syntax or referenced tables/columns in the Database Join dialog.","Ensure all ${VARIABLES} in the SQL are defined (KETTLE variables / environment) before execution.","Verify the step's database connection settings and that the DB is reachable."],"exampleFix":"// before: SQL referencing a renamed table\nString sql = \"SELECT * FROM cust_old WHERE id = ?\";\n// after\nString sql = \"SELECT * FROM customer WHERE id = ?\";","handlingStrategy":"validation","validationCode":"String resolved = transMeta.environmentSubstitute(meta.getSql());\nif (resolved.contains(\"${\")) throw new IllegalArgumentException(\"Unresolved variables in SQL: \" + resolved);\ntry (PreparedStatement ps = connection.prepareStatement(resolved)) { /* metadata prepared OK */ }","typeGuard":null,"tryCatchPattern":"try { transMeta.initializeVariablesFrom(null); }\ncatch (KettleStepException e) {\n  if (e.getMessage().contains(\"UnableToDetermineQueryFields\")) {\n    String sql = e.getMessage().substring(e.getMessage().indexOf(Const.CR) + 1);\n    log.error(\"Fix this SQL manually: {}\", sql);\n  }\n}","preventionTips":["Test the SQL in a DB client before putting it into the step","Define all Kettle variables used in the SQL at run time","Re-test metadata retrieval after schema migrations"],"tags":["kettle","sql","metadata"],"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"}