{"record":{"id":"df14691d5908e68c","repo":"pentaho/pentaho-kettle","slug":"dynamicsqlrow-exception-sqlempty","errorCode":null,"errorMessage":"DynamicSQLRow.Exception.SQLEmpty","messagePattern":"DynamicSQLRow\\.Exception\\.SQLEmpty","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRow.java","lineNumber":222,"sourceCode":"\n  }\n\n  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {\n    meta = (DynamicSQLRowMeta) smi;\n    data = (DynamicSQLRowData) sdi;\n\n    Object[] r = getRow(); // Get row from input rowset & set row busy!\n    if ( r == null ) { // no more input to be expected...\n      setOutputDone();\n      return false;\n    }\n    if ( first ) {\n      if ( Utils.isEmpty( meta.getSQLFieldName() ) ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"DynamicSQLRow.Exception.SQLFieldNameEmpty\" ) );\n      }\n\n      if ( Utils.isEmpty( meta.getSql() ) ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"DynamicSQLRow.Exception.SQLEmpty\" ) );\n      }\n\n      // cache the position of the field\n      if ( data.indexOfSQLField < 0 ) {\n        data.indexOfSQLField = getInputRowMeta().indexOfValue( meta.getSQLFieldName() );\n        if ( data.indexOfSQLField < 0 ) {\n          // The field is unreachable !\n          throw new KettleException( BaseMessages.getString( PKG, \"DynamicSQLRow.Exception.FieldNotFound\", meta\n            .getSQLFieldName() ) );\n        }\n      }\n    }\n    try {\n      lookupValues( getInputRowMeta(), r );\n\n      if ( checkFeedback( getLinesRead() ) ) {\n        if ( log.isDetailed() ) {\n          logDetailed( BaseMessages.getString( PKG, \"DynamicSQLRow.Log.LineNumber\" ) + getLinesRead() );","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRow.java#L204-L240","documentation":"DynamicSQLRow.processRow validates on the first row that the step's configured SQL template (meta.getSql()) is non-empty and throws this KettleException otherwise. Without a base SQL template the step has nothing to execute.","triggerScenarios":"Executing a Dynamic SQL Row step whose 'SQL' text box was left empty in the dialog, or whose saved metadata lost the sql attribute.","commonSituations":"Step added but never configured; XML/repository record with an empty <sql> tag; template accidentally cleared while editing the transformation.","solutions":["Open the step dialog and enter the SQL template (use ? placeholders as needed)","Confirm the template is saved in the step XML (<sql> tag)","Re-save the transformation after entering the SQL","If SQL should come entirely from the field, still provide a minimal template consistent with the step's design"],"exampleFix":"// before\n<sql></sql>\n// after\n<sql>SELECT id, name FROM customers WHERE region = ?</sql>","handlingStrategy":"validation","validationCode":"if (meta.getSql() == null || meta.getSql().trim().isEmpty()) {\n  throw new IllegalStateException(\"Dynamic SQL Row: SQL template is empty\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  // processRow validation\n} catch (KettleException e) {\n  logError(\"Enter the SQL template in the Dynamic SQL Row step\", e);\n  stopAll(); setErrors(1);\n  return false;\n}","preventionTips":["Never save the step with an empty SQL box","Keep SQL templates in version control alongside the .ktr","Verify <sql> tag content after importing/merging transformations","Preview the step to confirm configuration loads correctly"],"tags":["kettle","sql","configuration"],"backgroundTag":"empty-required-field","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"}