pentaho/pentaho-kettle · error · KettleException
VALUEMAPPER0004
VALUEMAPPER0004
Error message
ValueMapper.RuntimeError.OnlyOneEmptyMappingAllowed.VALUEMAPPER0004
What it means
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.
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.
Example fix
// before (meta config)
sourceValue = {"", "", "A"}
// after
sourceValue = {"", "A"} // only one empty catch-all mapping Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
int empties = 0;
for (String s : meta.getSourceValue()) if (Utils.isEmpty(s)) empties++;
if (empties > 1) throw new IllegalArgumentException("Only one empty source mapping allowed"); Try / catch
try {
processRow();
} catch (KettleException e) {
if (e.getMessage().contains("VALUEMAPPER0004")) {
logError("Remove duplicate empty source values in ValueMapper");
}
throw e;
} Prevention
- 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
When it happens
Trigger: processRow runs and meta.getSourceValue() contains two or more null/empty entries; the first sets data.emptyFieldIndex, the second throws.
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- VALUEMAPPER0004
- VALUEMAPPER0005
- VALUEMAPPER0006
- API coding error: please specify the conversion metadata…
- Calculator.Error.NoNameField
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/682be789af514d0b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/valuemapper/ValueMapper.java:89
if ( data.keynr < 0 ) {
String message =
BaseMessages.getString( PKG, "ValueMapper.RuntimeError.FieldToUseNotFound.VALUEMAPPER0001", meta
.getFieldToUse(), Const.CR, getInputRowMeta().getString( r ) );
logError( message );
setErrors( 1 );
stopAll();
return false;
}
// If there is an empty entry: we map null or "" to the target at the index
// 0 or 1 empty mapping is allowed, not 2 or more.
//
for ( int i = 0; i < meta.getSourceValue().length; i++ ) {
if ( Utils.isEmpty( meta.getSourceValue()[i] ) ) {
if ( data.emptyFieldIndex < 0 ) {
data.emptyFieldIndex = i;
} else {
throw new KettleException( BaseMessages.getString(
PKG, "ValueMapper.RuntimeError.OnlyOneEmptyMappingAllowed.VALUEMAPPER0004" ) );
}
}
}
data.sourceValueMeta = getInputRowMeta().getValueMeta( data.keynr );
if ( Utils.isEmpty( meta.getTargetField() ) ) {
data.outputValueMeta = data.outputMeta.getValueMeta( data.keynr ); // Same field
} else {
data.outputValueMeta = data.outputMeta.searchValueMeta( meta.getTargetField() ); // new field
}
}
Object sourceData = r[data.keynr];
String source = data.sourceValueMeta.getCompatibleString( sourceData );
String target = null;View on GitHub (pinned to f3058517a1)