pentaho/pentaho-kettle · error · KettleValueException

Unable to add months with a null value

Error message

Unable to add months with a null value

What it means

ValueDataUtil.addMonths refuses to operate when the input date (dataA) is null; it throws this KettleValueException instead of returning null. The library treats null date input as a caller error for month arithmetic rather than silently propagating null.

Solutions

  1. Guard the input: use an NVL/Coalesce or 'IF field A IS NULL THEN ...' step before the add-months calculation
  2. Check dataA != null in your Java/UDF code before calling ValueDataUtil.addMonths
  3. Fix the upstream step so the date field is populated (or explicitly set a default date)
  4. If null propagation is desired, wrap the call in try-catch for KettleValueException and return null

Example fix

// before
Object result = ValueDataUtil.addMonths( metaA, dataA, metaB, monthsToAdd );
// after
Object result = ( dataA == null ) ? null : ValueDataUtil.addMonths( metaA, dataA, metaB, monthsToAdd );
Defensive patterns

Strategy: type-guard

Validate before calling

if ( dataA == null ) { return null; } // or NVL default
if ( metaA != null && !metaA.isDate() ) throw new IllegalArgumentException( "Field A must be a Date" );

Type guard

boolean isNonNullDate( ValueMetaInterface m, Object d ) { return d != null && m != null && m.isDate(); }

Try / catch

try {
  return ValueDataUtil.addMonths( metaA, dataA, metaB, dataB );
} catch ( KettleValueException e ) {
  if ( "Unable to add months with a null value".equals( e.getMessage() ) ) return null; // treat as null propagation
  throw e;
}

Prevention

When it happens

Trigger: Calling ValueDataUtil.addMonths(metaA, null, metaB, dataB) (or via Calculator step 'A + B months' where field A evaluates to null) — the else branch after the cal-manipulation runs and throws.

Common situations: Upstream step produced a null date (failed lookup, empty CSV field) and the stream still calls the add-months calculation without an IFNULL/NVL guard; date conversion step failed silently earlier in the flow.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:1569

      int month = cal.get( Calendar.MONTH );
      int day = cal.get( Calendar.DAY_OF_MONTH );

      month += metaB.getInteger( dataB ).intValue();

      int newyear = year + (int) Math.floor( month / 12 );
      int newmonth = month % 12;

      cal.set( newyear, newmonth, 1 );
      int newday = cal.getActualMaximum( Calendar.DAY_OF_MONTH );
      if ( newday < day ) {
        cal.set( Calendar.DAY_OF_MONTH, newday );
      } else {
        cal.set( Calendar.DAY_OF_MONTH, day );
      }

      return ( cal.getTime() );
    } else {
      throw new KettleValueException( "Unable to add months with a null value" );
    }

  }

  /**
   * Returns the number of days that have elapsed between dataA and dataB.
   *
   * @param metaA
   * @param dataA
   *          The "end date"
   * @param metaB
   * @param dataB
   *          The "start date"
   * @param resultType
   *          The "result type" (ms, s, mn, h, d)
   * @return Number of days
   * @throws KettleValueException
   */

View on GitHub (pinned to f3058517a1)