{"record":{"id":"79e0d037fa5f9d1a","repo":"pentaho/pentaho-kettle","slug":"delete-exception-fieldrequired","errorCode":"Delete.Exception.FieldRequired","errorMessage":"Delete.Exception.FieldRequired","messagePattern":"Delete\\.Exception\\.FieldRequired","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/delete/Delete.java","lineNumber":122,"sourceCode":"              meta.getDatabaseMeta().getQuotedSchemaTableCombination(\n                      environmentSubstitute( meta.getSchemaName() ), environmentSubstitute( meta.getTableName() ) );\n\n      // lookup the values!\n      if ( log.isDetailed() ) {\n        logDetailed( BaseMessages.getString( PKG, \"Delete.Log.CheckingRow\" ) + getInputRowMeta().getString( r ) );\n      }\n\n      // TODO: maybe handle if the fields in lookupFields are null\n      int len = meta.getKeyFields().length;\n      data.keynrs = new int[len];\n      data.keynrs2 = new int[len];\n      for ( int i = 0; i < len; i++ ) {\n        data.keynrs[i] = getInputRowMeta().indexOfValue( meta.getKeyFields()[i].getKeyStream() );\n        if ( data.keynrs[i] < 0 && // couldn't find field!\n                !\"IS NULL\".equalsIgnoreCase( meta.getKeyFields()[i].getKeyCondition() ) && // No field needed!\n                !\"IS NOT NULL\".equalsIgnoreCase( meta.getKeyFields()[i].getKeyCondition() ) // No field needed!\n        ) {\n          throw new KettleStepException( BaseMessages.getString( PKG, \"Delete.Exception.FieldRequired\",\n                  meta.getKeyFields()[i].getKeyStream() ) );\n        }\n\n        data.keynrs2[i] = ( meta.getKeyFields()[i].getKeyStream2() != null\n                && meta.getKeyFields()[i].getKeyStream2().length() > 0 )\n                ? getInputRowMeta().indexOfValue( meta.getKeyFields()[i].getKeyStream2() ) : -1;\n        if ( data.keynrs2[i] < 0 && // couldn't find field!\n                \"BETWEEN\".equalsIgnoreCase( meta.getKeyFields()[i].getKeyCondition() ) // 2 fields needed!\n        ) {\n          throw new KettleStepException( BaseMessages.getString( PKG, \"Delete.Exception.FieldRequired\",\n                  meta.getKeyFields()[i].getKeyStream2() ) );\n        }\n\n        if ( log.isDebug() ) {\n          logDebug( BaseMessages.getString( PKG, \"Delete.Log.FieldInfo\",\n                  meta.getKeyFields()[i].getKeyStream() ) + data.keynrs[i] );\n        }\n      }","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/delete/Delete.java#L104-L140","documentation":"The Delete step locates each configured key field in the incoming row to build the WHERE clause for the DELETE statement. When a key field is missing from the input row — and its condition is not IS NULL / IS NOT NULL (which need no value) — the step throws this KettleStepException naming the missing field.","triggerScenarios":"processRow runs while meta.getKeyFields()[i].getKeyStream() names a field not present in getInputRowMeta(), with any key condition other than 'IS NULL' or 'IS NOT NULL'.","commonSituations":"Upstream step renamed/removed the key field; typo in the key stream name; key condition configured as '=' while the field never arrives; wrong input stream connected in a multi-input branch.","solutions":["Correct the key field name in the Delete step to match an actual field in the input stream.","Add the missing key field upstream (Select values / previous step output) before the Delete step.","If the key is intentionally value-less, change its condition to 'IS NULL' or 'IS NOT NULL' so no field value is required.","Inspect the incoming row layout (input step -> Show output fields) and fix case-sensitive mismatches."],"exampleFix":"// before: key stream 'id' not in stream\nLookup key: id = =\n// after\nLookup key: customer_id = =","handlingStrategy":"validation","validationCode":"for (DeleteMeta.KeyField kf : meta.getKeyFields()) {\n  boolean condNeedsValue = !\"IS NULL\".equalsIgnoreCase(kf.getKeyCondition())\n      && !\"IS NOT NULL\".equalsIgnoreCase(kf.getKeyCondition());\n  if (condNeedsValue && getInputRowMeta().indexOfValue(kf.getKeyStream()) < 0)\n    throw new IllegalArgumentException(\"Missing Delete key field: \"+kf.getKeyStream());\n}","typeGuard":"boolean keyNeedsField(String condition){\n  return !\"IS NULL\".equalsIgnoreCase(condition) && !\"IS NOT NULL\".equalsIgnoreCase(condition);\n}","tryCatchPattern":"try { processRow(); }\ncatch (KettleStepException e) {\n  logError(\"Delete key field missing: \" + e.getMessage(), e);\n  setErrors(1); stopAll(true);\n}","preventionTips":["Verify key field names against the input row layout before running.","Use IS NULL / IS NOT NULL conditions when no field value is needed.","Fix upstream renames before the Delete step.","Check the correct input stream is connected on multi-input transforms."],"tags":["kettle","delete-step","missing-field"],"backgroundTag":"missing-required-argument","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"}