pentaho/pentaho-kettle · error · JavaScriptException
Could not convert to the given local format.
Error message
Could not convert to the given local format.
What it means
This error is thrown by the date2str JavaScript function in ScriptValuesAddedFunctions when formatting a Date with an explicit locale fails. The 3-argument form builds a SimpleDateFormat with a user-supplied pattern and a 2-letter locale string; any exception in that path (bad pattern, bad locale, wrong argument types) is caught and re-thrown as this generic runtime error. It deliberately masks the underlying exception, so the real cause must be inferred from the arguments.
Solutions
- Validate the pattern with Java's SimpleDateFormat outside the script (new SimpleDateFormat(pattern, locale)) to see the real underlying exception.
- Ensure the first argument is a Date (use new Date(...) or d2i/date parsing first) and not null/undefined.
- Use a 2-letter ISO-639 locale code (e.g. 'de', 'fr'); longer codes are rejected before this path.
- Quote literal characters in the pattern with single quotes (e.g. "yyyy-MM-dd'T'HH:mm:ss").
Example fix
// before date2str(orderDate, "yyyy-mm-dd hh:mm:ss", "en_US") // after date2str(orderDate, "yyyy-MM-dd HH:mm:ss", "en")
Defensive patterns
Strategy: validation
Validate before calling
// JS in Kettle step
function safeDate2str(d, fmt, loc) {
if (d == null || fmt == null || loc == null || loc.length != 2) return null;
return date2str(d, fmt, loc);
} Type guard
function isDate(v) { return v != null && typeof v.getTime === 'function'; } Try / catch
try { result = date2str(d, fmt, loc); } catch (e) { result = null; /* log e for step failure diagnostics */ } Prevention
- Always pass a real Date object, not a string
- Use 2-letter ISO-639 locale codes
- Quote literal characters in SimpleDateFormat patterns
- Test the pattern in plain Java when debugging
When it happens
Trigger: Calling date2str(date, pattern, locale) in a Kettle/JavaScript step where: the pattern contains illegal SimpleDateFormat characters (e.g. "yyyy-mm-dd" intended but with unquoted literals like 'T' handled wrong, or stray quotes), the locale argument is not exactly 2 characters (which first raises the 2-char check only when the check branch is reached; other arg-shape failures land here), the first argument is not a Date/number, or the arguments are null/undefined so SimpleDateFormat construction throws.
Common situations: Transformation developers passing a string timestamp instead of a Date object; using locale codes like 'en_US' (5 chars) instead of 'en'; typos in the format mask such as unmatched single quotes; migrating scripts between Kettle versions where date2str argument order or null handling changed.
Related errors
- Could not convert to local format.
- Could not convert to the given format.
- Could not convert to the given local format.
- Locale is not 2 characters long.
- Please provide a valid date to the function call date2str.
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/ffa371d144acdb5b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java:1178
try {
if ( isNull( ArgList, new int[] { 0, 1, 2 } ) ) {
return null;
} else if ( isUndefined( ArgList, new int[] { 0, 1, 2 } ) ) {
return Context.getUndefinedValue();
}
java.util.Date dArg1 = (java.util.Date) Context.jsToJava( ArgList[0], java.util.Date.class );
DateFormat dfFormatter;
String sArg2 = Context.toString( ArgList[1] );
String sArg3 = Context.toString( ArgList[2] );
if ( sArg3.length() == 2 ) {
Locale dfLocale = EnvUtil.createLocale( sArg3.toLowerCase() );
dfFormatter = new SimpleDateFormat( sArg2, dfLocale );
oRC = dfFormatter.format( dArg1 );
} else {
throw Context.reportRuntimeError( "Locale is not 2 characters long." );
}
} catch ( Exception e ) {
throw Context.reportRuntimeError( "Could not convert to the given local format." );
}
break;
case 4:
try {
if ( isNull( ArgList, new int[] { 0, 1, 2, 3 } ) ) {
return null;
} else if ( isUndefined( ArgList, new int[] { 0, 1, 2, 3 } ) ) {
return Context.getUndefinedValue();
}
java.util.Date dArg1 = (java.util.Date) Context.jsToJava( ArgList[0], java.util.Date.class );
DateFormat dfFormatter;
String sArg2 = Context.toString( ArgList[1] );
String sArg3 = Context.toString( ArgList[2] );
String sArg4 = Context.toString( ArgList[3] );
// If the timezone is not recognized, java will automatically
// take GMT.
TimeZone tz = TimeZone.getTimeZone( sArg4 );View on GitHub (pinned to f3058517a1)