pentaho/pentaho-kettle · error · RuntimeException

Locale is not 2 characters long.

Error message

Locale is not 2 characters long.

What it means

In the 3-argument date2str branch (date, format, locale), the locale argument must be exactly 2 characters. When it isn't, the code throws 'Locale is not 2 characters long.' before attempting to build the SimpleDateFormat with EnvUtil.createLocale.

Solutions

  1. Pass a 2-letter language code: date2str(d,'yyyy-MM-dd','de').
  2. Truncate regional values with substring(0,2) when needed.
  3. Validate the locale variable length before the call.
  4. If you need country-specific formatting, note this API only accepts the 2-letter language code.

Example fix

// before
var s = date2str(d, 'yyyy-MM-dd', 'de_DE');
// after
var s = date2str(d, 'yyyy-MM-dd', 'de');
Defensive patterns

Strategy: validation

Validate before calling

if (typeof loc !== 'string' || loc.length !== 2) throw new Error('date2str locale must be 2 chars, got: ' + loc);

Type guard

function isTwoLetterLocale(v) { return typeof v === 'string' && /^[a-zA-Z]{2}$/.test(v); }

Try / catch

try { var s = date2str(d, fmt, loc); } catch (e) { if (String(e.message).indexOf('not 2 characters long') >= 0) { s = date2str(d, fmt, String(loc).substring(0,2)); } else { throw e; } }

Prevention

When it happens

Trigger: date2str(date, format, locale) with locale length != 2, e.g. date2str(d,'yyyy-MM-dd','en_US'), 'eng', or an empty string.

Common situations: Passing full locale tags or country codes; locale sourced from a variable that is empty; confusion with java.util.Locale constructors that accept language+country separately.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

        }
        break;
      case 3:
        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];

View on GitHub (pinned to f3058517a1)