pentaho/pentaho-kettle · warning · IllegalArgumentException

Strings must not be null

Error message

Strings must not be null

What it means

PentahoJaroWinklerDistance.apply throws an IllegalArgumentException when either of the two CharSequences being compared is null. The Jaro/Jaro-Winkler similarity algorithm requires two non-null strings; null inputs are a caller contract violation rather than a data problem.

Solutions

  1. Null-check both strings before calling apply or the similitude helpers.
  2. Treat null as empty string ("" ) when a null field means 'no value' for your matching logic.
  3. If null should score as zero similarity, short-circuit in your own wrapper: if either is null, return 0.

Example fix

// before
double score = dist.getJaroWinkler_Similitude(row.getString("name"), refName);
// after
String name = row.getString("name");
double score = (name == null || refName == null) ? 0.0 : dist.getJaroWinkler_Similitude(name, refName);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean comparable = (left != null && right != null);

Type guard

boolean isNonNullString(CharSequence cs) { return cs != null; }

Try / catch

try {
  score = dist.getJaroWinkler_Similitude(a, b);
} catch (IllegalArgumentException e) {
  score = 0.0; // treat null as zero similarity
}

Prevention

When it happens

Trigger: Calling apply(null, s), apply(s, null) or apply(null, null), directly or indirectly through getJaro_Similitude / getJaroWinkler_Similitude with a null operand (typically a null field value from a data row).

Common situations: Fuzzy-matching / dedup steps feeding null column values (e.g. missing address or name fields) into the similarity calculator without a prior null check.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/util/PentahoJaroWinklerDistance.java:86

   * distance.apply("hippo", "elephant") = 0.44
   * distance.apply("hippo", "zzzzzzzz") = 0.0
   * distance.apply("hello", "hallo")    = 0.88
   * distance.apply("ABC Corporation", "ABC Corp") = 0.93
   * distance.apply("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95
   * distance.apply("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
   * distance.apply("PENNSYLVANIA", "PENNCISYLVNIA")    = 0.88
   * </pre>
   *
   * @param left the first String, must not be null
   * @param right the second String, must not be null
   * @return result distance
   * @throws IllegalArgumentException if either String input {@code null}
   */
  public void apply( final CharSequence left, final CharSequence right ) {
    final double defaultScalingFactor = 0.1;

    if ( left == null || right == null ) {
      throw new IllegalArgumentException( "Strings must not be null" );
    }

    final int[] mtp = matches( left, right );
    final double m = mtp[0];
    if ( m == 0 ) {
      j = 0D;
      jw = 0D;
    } else {
      j = ( ( m / left.length() + m / right.length() + ( m - mtp[1] ) / m ) ) / 3;
      jw = j < 0.7D ? j : j + Math.min( defaultScalingFactor, 1D / mtp[3] ) * mtp[2] * ( 1D - j );
    }
  }

  /**
   * This method returns the Jaro-Winkler string matches, transpositions, prefix, max array.
   *
   * @param first the first string to be matched
   * @param second the second string to be matched

View on GitHub (pinned to f3058517a1)