{"record":{"id":"682be789af514d0b","repo":"pentaho/pentaho-kettle","slug":"valuemapper0004","errorCode":"VALUEMAPPER0004","errorMessage":"ValueMapper.RuntimeError.OnlyOneEmptyMappingAllowed.VALUEMAPPER0004","messagePattern":"ValueMapper\\.RuntimeError\\.OnlyOneEmptyMappingAllowed\\.VALUEMAPPER0004","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/valuemapper/ValueMapper.java","lineNumber":89,"sourceCode":"      if ( data.keynr < 0 ) {\n        String message =\n          BaseMessages.getString( PKG, \"ValueMapper.RuntimeError.FieldToUseNotFound.VALUEMAPPER0001\", meta\n            .getFieldToUse(), Const.CR, getInputRowMeta().getString( r ) );\n        logError( message );\n        setErrors( 1 );\n        stopAll();\n        return false;\n      }\n\n      // If there is an empty entry: we map null or \"\" to the target at the index\n      // 0 or 1 empty mapping is allowed, not 2 or more.\n      //\n      for ( int i = 0; i < meta.getSourceValue().length; i++ ) {\n        if ( Utils.isEmpty( meta.getSourceValue()[i] ) ) {\n          if ( data.emptyFieldIndex < 0 ) {\n            data.emptyFieldIndex = i;\n          } else {\n            throw new KettleException( BaseMessages.getString(\n              PKG, \"ValueMapper.RuntimeError.OnlyOneEmptyMappingAllowed.VALUEMAPPER0004\" ) );\n          }\n        }\n      }\n\n      data.sourceValueMeta = getInputRowMeta().getValueMeta( data.keynr );\n\n      if ( Utils.isEmpty( meta.getTargetField() ) ) {\n        data.outputValueMeta = data.outputMeta.getValueMeta( data.keynr ); // Same field\n\n      } else {\n        data.outputValueMeta = data.outputMeta.searchValueMeta( meta.getTargetField() ); // new field\n      }\n    }\n\n    Object sourceData = r[data.keynr];\n    String source = data.sourceValueMeta.getCompatibleString( sourceData );\n    String target = null;","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/valuemapper/ValueMapper.java#L71-L107","documentation":"ValueMapper allows at most one source mapping with an empty source value (the empty string acts as a catch-all 'map empty/missing values' entry). During processRow the step scans all source values; if a second empty one is found after data.emptyFieldIndex is already set, it aborts with VALUEMAPPER0004.","triggerScenarios":"processRow runs and meta.getSourceValue() contains two or more null/empty entries; the first sets data.emptyFieldIndex, the second throws.","commonSituations":"User adds multiple blank rows in the 'Source value / Target value' mapping grid intending multiple defaults; pasting mappings that include empty cells; programmatic meta construction leaving unset source values.","solutions":["Open the ValueMapper step and delete or fill in all but one blank Source value row.","Give each mapping row a concrete source value; use the single empty row only for the default/empty mapping.","Inspect the step's field list in the .ktr XML and remove extra empty <source_value> entries.","If building meta in code, validate sourceValue array for duplicates of empty before saving/running."],"exampleFix":"// before (meta config)\nsourceValue = {\"\", \"\", \"A\"}\n// after\nsourceValue = {\"\", \"A\"} // only one empty catch-all mapping","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nint empties = 0;\nfor (String s : meta.getSourceValue()) if (Utils.isEmpty(s)) empties++;\nif (empties > 1) throw new IllegalArgumentException(\"Only one empty source mapping allowed\");","typeGuard":null,"tryCatchPattern":"try {\n  processRow();\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"VALUEMAPPER0004\")) {\n    logError(\"Remove duplicate empty source values in ValueMapper\");\n  }\n  throw e;\n}","preventionTips":["Keep at most one blank Source value row (the default mapping)","Fill in source values for all real mappings","Validate meta programmatically before saving generated transformations"],"tags":["pdi","kettle","valuemapper","duplicate-config"],"backgroundTag":"conflicting-config-options","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"}