pentaho/pentaho-kettle · error · RuntimeException

Could not convert to the given local format.

Error message

Could not convert to the given local format.

What it means

Catch-all rethrow for the 3-argument date2str branch (date, format, locale): any failure — non-Date first argument, invalid pattern, wrong-length locale, or locale the JDK doesn't recognize — is wrapped into 'Could not convert to the given local format.' with no underlying message attached.

Solutions

  1. Confirm the first argument is a java.util.Date (convert strings with str2date first).
  2. Verify the format is a valid SimpleDateFormat pattern and the locale is a 2-letter code.
  3. Validate arguments before the call to avoid the opaque wrapper message.
  4. Isolate the call in try/catch and log each argument's type/value to find the offender.
  5. Compare with the working 2-argument form to determine whether format or locale is at fault.

Example fix

// before
var s = date2str('2024-01-01', 'qqqq', 'en'); // String + bad pattern
// after
var s = date2str(str2date('2024-01-01','yyyy-MM-dd'), 'yyyy-MM-dd', 'en');
Defensive patterns

Strategy: try-catch

Validate before calling

function safeDate2str3(d, fmt, loc) {
  if (!isJavaDate(d)) d = str2date(String(d), 'yyyy-MM-dd');
  if (typeof loc !== 'string' || loc.length !== 2) loc = String(loc).substring(0, 2);
  return date2str(d, fmt, loc);
}

Type guard

function isJavaDate(v) { return v != null && typeof v === 'object' && v.getClass && String(v.getClass()).indexOf('java.util.Date') >= 0; }

Try / catch

try { var s = date2str(d, fmt, loc); } catch (e) { if (String(e.message).indexOf('Could not convert to the given local format') >= 0) { Logger.log('args: d=' + d + ' fmt=' + fmt + ' loc=' + loc); s = null; } else { throw e; } }

Prevention

When it happens

Trigger: date2str(date, format, locale) throwing inside the try block: ClassCastException on the date, IllegalArgumentException from a bad SimpleDateFormat pattern, or the nested 'Locale is not 2 characters long' RuntimeException.

Common situations: String instead of Date; invalid format letters; locale of the wrong length or an unsupported code; nulls slipping past the isNull check because they arrive as non-null non-Date values.

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/b94eaaca0f6d4475. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/script/ScriptAddedFunctions.java:1144

        try {
          if ( isNull( ArgList, new int[] { 0, 1, 2 } ) ) {
            return null;
          } else if ( isUndefined( ArgList, new int[] { 0, 1, 2 } ) ) {
            return undefinedValue;
          }
          java.util.Date dArg1 = (java.util.Date) ArgList[0];
          DateFormat dfFormatter;
          String sArg2 = (String) ArgList[1];
          String sArg3 = (String) ArgList[2];
          if ( sArg3.length() == 2 ) {
            Locale dfLocale = EnvUtil.createLocale( sArg3.toLowerCase() );
            dfFormatter = new SimpleDateFormat( sArg2, dfLocale );
            oRC = dfFormatter.format( dArg1 );
          } else {
            throw new RuntimeException( "Locale is not 2 characters long." );
          }
        } catch ( Exception e ) {
          throw new RuntimeException( "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 undefinedValue;
          }
          java.util.Date dArg1 = (java.util.Date) ArgList[0];
          DateFormat dfFormatter;
          String sArg2 = (String) ArgList[1];
          String sArg3 = (String) ArgList[2];
          String sArg4 = (String) ArgList[3];

          // If the timezone is not recognized, java will automatically
          // take GMT.
          TimeZone tz = TimeZone.getTimeZone( sArg4 );

View on GitHub (pinned to f3058517a1)