{"record":{"id":"74573d37e1d86fa5","repo":"pentaho/pentaho-kettle","slug":"tostring-couldn-t-convert-string-to-number-non-numeric","errorCode":null,"errorMessage":"<toString()> : couldn't convert String to number : non-numeric character found at position <parsePosition.getIndex() + 1> for value [<string>]","messagePattern":"<toString\\(\\)> : couldn't convert String to number : non-numeric character found at position <parsePosition\\.getIndex\\(\\) \\+ 1> for value \\[<string>\\]","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java","lineNumber":1341,"sourceCode":"  protected synchronized Long convertStringToInteger( String string ) throws KettleValueException {\n    string = Const.trimToType( string, getTrimType() ); // see if trimming needs\n    // to be performed before\n    // conversion\n\n    if ( Utils.isEmpty( string ) ) {\n      return null;\n    }\n\n    try {\n      Number number;\n      if ( lenientStringToNumber ) {\n        number = getDecimalFormat( false ).parse( string );\n      } else {\n        ParsePosition parsePosition = new ParsePosition( 0 );\n        number = getDecimalFormat( false ).parse( string, parsePosition );\n\n        if ( parsePosition.getIndex() < string.length() ) {\n          throw new KettleValueException( toString()\n            + \" : couldn't convert String to number : non-numeric character found at position \"\n            + ( parsePosition.getIndex() + 1 ) + \" for value [\" + string + \"]\" );\n        }\n      }\n\n      if ( number instanceof Double && ( number.doubleValue() < Long.MIN_VALUE\n        || number.doubleValue() > Long.MAX_VALUE ) ) {\n        log.logBasic( \"Value [\" + string + \"] is out of range for Integer.\" );\n        if ( !ignoreOutOfRange ) {\n          throw new KettleValueException( toString()\n            + \" : couldn't convert String to Integer : value Out of Range [\" + string\n            + \"]. Change the destination data type or round to the nearest value possible for Integer by setting \"\n            + \"property KETTLE_IGNORE_OUT_OF_RANGE_EXCEPTION to \\\"Y\\\". \" );\n        }\n      }\n\n      return new Long( number.longValue() );\n    } catch ( Exception e ) {","sourceCodeStart":1323,"sourceCodeEnd":1359,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java#L1323-L1359","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pre-validate the string matches ^[+-]?\\\\d+$ (after removing expected separators) before conversion","Set an appropriate mask with setConversionMask or convert the field to TYPE_NUMBER if it holds decimals","Trim whitespace/non-breaking spaces and strip units/symbols first","Use transformation error handling to route offending rows aside and inspect them"],"exampleFix":"// before\nLong n = valueMeta.getInteger(\"1 234 kg\"); // throws: non-numeric char at position 7\n// after\nString cleaned = raw.replaceAll(\"\\\\D\", \"\");\nLong n = valueMeta.getInteger(cleaned);","handlingStrategy":"validation","validationCode":"static boolean isCleanInteger(String s) {\n  if (s == null) return false;\n  String t = s.trim().replace(\"\\u00A0\", \"\");\n  return t.matches(\"[+-]?\\\\d+\");\n}","typeGuard":"static boolean parsesFullyAsLong(java.text.DecimalFormat fmt, String s) {\n  java.text.ParsePosition pos = new java.text.ParsePosition(0);\n  Number n = fmt.parse(s, pos);\n  return n != null && pos.getIndex() == s.trim().length();\n}","tryCatchPattern":"try {\n  Long n = valueMeta.getInteger(raw);\n} catch (KettleValueException e) {\n  log.error(\"Bad integer '\" + raw + \"' at char \" + e.getMessage());\n  routeToErrorRow(raw);\n  return null;\n}","preventionTips":["Route decimal-looking data to Number fields, not Integer","Strip units, percent signs, and non-breaking spaces before parsing","Pre-validate with DecimalFormat + ParsePosition full-consumption check","Configure transformation error handling with a rejected-rows stream"],"tags":["integer","parsing","decimalformat","kettle"],"backgroundTag":"invalid-argument-format","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"}