pentaho/pentaho-kettle · error · KettleValueException

<toString()> : couldn't convert String to number …

Error message

<toString()> : couldn't convert String to number : non-numeric character found at position <parsePosition.getIndex() + 1> for value [<string>]

What it means

Thrown by ValueMetaBase.convertStringToInteger (Long path) when DecimalFormat.parse(string, parsePosition) stops before consuming the whole string, i.e. a non-numeric character appears after the numeric prefix. The message gives the 1-based position via parsePosition.getIndex() + 1 and the offending value.

Solutions

  1. Pre-validate the string matches ^[+-]?\\d+$ (after removing expected separators) before conversion
  2. Set an appropriate mask with setConversionMask or convert the field to TYPE_NUMBER if it holds decimals
  3. Trim whitespace/non-breaking spaces and strip units/symbols first
  4. Use transformation error handling to route offending rows aside and inspect them

Example fix

// before
Long n = valueMeta.getInteger("1 234 kg"); // throws: non-numeric char at position 7
// after
String cleaned = raw.replaceAll("\\D", "");
Long n = valueMeta.getInteger(cleaned);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isCleanInteger(String s) {
  if (s == null) return false;
  String t = s.trim().replace("\u00A0", "");
  return t.matches("[+-]?\\d+");
}

Type guard

static boolean parsesFullyAsLong(java.text.DecimalFormat fmt, String s) {
  java.text.ParsePosition pos = new java.text.ParsePosition(0);
  Number n = fmt.parse(s, pos);
  return n != null && pos.getIndex() == s.trim().length();
}

Try / catch

try {
  Long n = valueMeta.getInteger(raw);
} catch (KettleValueException e) {
  log.error("Bad integer '" + raw + "' at char " + e.getMessage());
  routeToErrorRow(raw);
  return null;
}

Prevention

When it happens

Trigger: Calling getInteger()/convertStringToInteger() with strings like '12a3', '1 000,5x', or values with trailing characters that don't match the integer format mask; also when decimal separators appear where the mask expects an integer.

Common situations: Decimal values ('12.5') fed into an Integer field; trailing percent signs, units, or footnotes; thousand separators not matching the configured mask; Excel exports with invisible trailing characters.

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


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/74573d37e1d86fa5. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:1341

  protected synchronized Long convertStringToInteger( String string ) throws KettleValueException {
    string = Const.trimToType( string, getTrimType() ); // see if trimming needs
    // to be performed before
    // conversion

    if ( Utils.isEmpty( string ) ) {
      return null;
    }

    try {
      Number number;
      if ( lenientStringToNumber ) {
        number = getDecimalFormat( false ).parse( string );
      } else {
        ParsePosition parsePosition = new ParsePosition( 0 );
        number = getDecimalFormat( false ).parse( string, parsePosition );

        if ( parsePosition.getIndex() < string.length() ) {
          throw new KettleValueException( toString()
            + " : couldn't convert String to number : non-numeric character found at position "
            + ( parsePosition.getIndex() + 1 ) + " for value [" + string + "]" );
        }
      }

      if ( number instanceof Double && ( number.doubleValue() < Long.MIN_VALUE
        || number.doubleValue() > Long.MAX_VALUE ) ) {
        log.logBasic( "Value [" + string + "] is out of range for Integer." );
        if ( !ignoreOutOfRange ) {
          throw new KettleValueException( toString()
            + " : couldn't convert String to Integer : value Out of Range [" + string
            + "]. Change the destination data type or round to the nearest value possible for Integer by setting "
            + "property KETTLE_IGNORE_OUT_OF_RANGE_EXCEPTION to \"Y\". " );
        }
      }

      return new Long( number.longValue() );
    } catch ( Exception e ) {

View on GitHub (pinned to f3058517a1)