pentaho/pentaho-kettle · error · KettleValueException
invalid hex digit ' '.
Error message
invalid hex digit '<c>'.
What it means
ValueDataUtil.chopHexToBytes converts a hex string to a byte array and validates every hex nibble character. When a character is outside 0-9, A-F, a-f it throws this KettleValueException naming the offending character, because the input is not a valid hex string (e.g. odd characters, whitespace, or odd-length garbage).
Solutions
- Inspect the reported character in the message and clean the input string: strip '0x' prefix, spaces, colons, dashes
- Validate the string with a regex ^[0-9A-Fa-f]+$ before calling chopHexToBytes
- Ensure the string length is even; pad with a leading '0' if odd
- Fix the upstream producer so it emits pure hex digits
Example fix
// before byte[] bytes = ValueDataUtil.chopHexToBytes( hexInput ); // "0x deadBEEF;" // after String clean = hexInput == null ? "" : hexInput.replaceAll( "[^0-9A-Fa-f]", "" ); if ( clean.length() % 2 == 1 ) clean = "0" + clean; byte[] bytes = ValueDataUtil.chopHexToBytes( clean );
Defensive patterns
Strategy: validation
Validate before calling
if ( hex == null || !hex.matches( "[0-9A-Fa-f]+" ) || hex.length() % 2 != 0 ) throw new IllegalArgumentException( "Invalid hex: " + hex );
Type guard
boolean isHexString( String s ) { return s != null && s.matches( "[0-9A-Fa-f]+" ) && s.length() % 2 == 0; } Try / catch
try {
return ValueDataUtil.chopHexToBytes( hex );
} catch ( KettleValueException e ) {
log.warn( "Bad hex input '" + hex + "' -> " + e.getMessage() );
return hex.replaceAll( "[^0-9A-Fa-f]", "" ).getBytes(); // fallback cleaning
} Prevention
- Strip '0x' prefixes and separators (spaces, colons, dashes) before decoding
- Enforce even length; left-pad odd-length strings with '0'
- Validate hex at data-ingestion time, not at decode time
- Beware look-alike characters (O vs 0, l vs 1) from manual entry
When it happens
Trigger: Calling ValueDataUtil.chopHexToBytes(hexString) (used by the HEX string decode path in transformations) where the string contains any character outside [0-9A-Fa-f], such as '0x' prefix, spaces, '-', 'g'-'z', or an embedded separator.
Common situations: Decoding a hex value that was copy-pasted with a '0x' prefix or colons/spaces (MAC-address style); a binary column exported with different encoding; uppercase/lowercase confusion is fine, but chars like 'O' vs '0' from OCR/manual entry fail.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- ChangeFileEncoding.Exception.TargetEncodingEmpty
- ConcatFields.Error.UnsupportedEncoding
- GPLoadDataOutput.Exception" + e.getMessage()
- PropertyInput.Error.CanNotReadFromFile
- The function call isCodepage requires 2 arguments.
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/36a081e2603117f1.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:1841
// we assume a leading 0 if the length is not even.
if ( ( len % 2 ) == 1 ) {
evenByte = false;
}
int nibble;
int i, j;
for ( i = 0, j = 0; i < len; i++ ) {
char c = hexString.charAt( i );
if ( ( c >= '0' ) && ( c <= '9' ) ) {
nibble = c - '0';
} else if ( ( c >= 'A' ) && ( c <= 'F' ) ) {
nibble = c - 'A' + 0x0A;
} else if ( ( c >= 'a' ) && ( c <= 'f' ) ) {
nibble = c - 'a' + 0x0A;
} else {
throw new KettleValueException( "invalid hex digit '" + c + "'." );
}
if ( evenByte ) {
nextByte = ( nibble << 4 );
} else {
nextByte += nibble;
chArray[j] = (char) nextByte;
j++;
}
evenByte = !evenByte;
}
return new String( chArray );
}
/**
* Change a string into its hexadecimal representation. E.g. if Value contains string "a" afterwards it would contain
* value "0061".View on GitHub (pinned to f3058517a1)