pentaho/pentaho-kettle · error · KettleValueException
<toString()> : couldn't convert string
Error message
<toString()> : couldn't convert string [<string>] to a date using format [<dateFormat>] on offset location <e.getErrorOffset()>
What it means
Thrown by ValueMetaBase.convertStringToDate when SimpleDateFormat.parse fails to parse the string using the value meta's date format. The message includes the value meta name, the offending string, the format pattern, and the character offset where parsing failed.
Solutions
- Set the correct conversion mask with setConversionDateFormat or getDateFormat matching the actual string (e.g. 'dd/MM/yyyy HH:mm:ss')
- Check the sample string against the pattern at the reported error offset
- Set the correct locale/timezone on the value meta (setDateFormatLocale/setDateFormatTimeZone)
- Pre-validate the string with a DateTimeFormatter before calling getDate
Example fix
// before
valueMeta.setConversionMask("yyyy-MM-dd"); // data is 25/03/1918 11:54
// after
valueMeta.setConversionMask("dd/MM/yyyy HH:mm"); Defensive patterns
Strategy: validation
Validate before calling
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.LocalDateTime;
static boolean isParseableDate(String s, String pattern) {
try {
DateTimeFormatter.ofPattern(pattern).parse(s);
return true;
} catch (DateTimeParseException | NullPointerException e) {
return false;
}
} Type guard
static boolean looksLikeDate(String s, String patternRegex) {
return s != null && !s.trim().isEmpty() && s.matches(patternRegex);
} Try / catch
try {
Date d = valueMeta.getDate(str);
} catch (KettleValueException e) {
log.error("Date parse failed: " + e.getMessage());
putRowToErrorRow(str, e.getMessage());
} Prevention
- Always set an explicit conversion mask matching the source data format
- Set matching DateFormatLocale and DateFormatTimeZone on the value meta
- Sample-validate date columns from new data sources before loading
- Watch for date-only masks applied to datetime strings (trailing chars)
When it happens
Trigger: Calling getDate()/convertStringToDate() on a String value that does not match getDateFormat().toPattern(); a null format (shown as 'null') with a non-default-parseable string; locale-sensitive patterns applied to strings produced under a different locale/timezone.
Common situations: Missing or wrong conversion mask (e.g. 'yyyy-MM-dd' vs 'dd/MM/yyyy'); data files changing date format after an upstream change; strings with trailing characters or empty input; parsing '25-03-1918 11:54' with a date-only format.
Related errors
- Could not apply the given format " + sArg2 + " on the…
- AnalyticQueryMeta.Exception.UnableToLoadStepInfoFromXML
- Could not apply local format for
- Could not convert the given String :
- Error_0001
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/313bb083db0b5c0c.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:936
if ( Utils.isEmpty( string ) ) {
return null;
}
try {
ParsePosition pp = new ParsePosition( 0 );
Date result = getDateFormat( TYPE_DATE ).parse( string, pp );
if ( pp.getErrorIndex() >= 0 ) {
// error happen
throw new ParseException( string, pp.getErrorIndex() );
}
// some chars can be after pp.getIndex(). That means, not full value was parsed. For example, for value
// "25-03-1918 11:54" and format "dd-MM-yyyy", value will be "25-03-1918 00:00" without any exception.
// If there are only spaces after pp.getIndex() - that means full values was parsed
return result;
} catch ( ParseException e ) {
String dateFormat = ( getDateFormat() != null ) ? getDateFormat().toPattern() : "null";
throw new KettleValueException( toString() + " : couldn't convert string [" + string
+ "] to a date using format [" + dateFormat + "] on offset location " + e.getErrorOffset(), e );
}
}
// DATE + NUMBER
protected Double convertDateToNumber( Date date ) {
return new Double( date.getTime() );
}
protected Date convertNumberToDate( Double number ) {
return new Date( number.longValue() );
}
// DATE + INTEGER
protected Long convertDateToInteger( Date date ) {
return new Long( date.getTime() );View on GitHub (pinned to f3058517a1)