{"record":{"id":"30375d38edd3e34d","repo":"pentaho/pentaho-kettle","slug":"unable-to-add-months-with-a-null-value","errorCode":null,"errorMessage":"Unable to add months with a null value","messagePattern":"Unable to add months with a null value","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java","lineNumber":1569,"sourceCode":"      int month = cal.get( Calendar.MONTH );\n      int day = cal.get( Calendar.DAY_OF_MONTH );\n\n      month += metaB.getInteger( dataB ).intValue();\n\n      int newyear = year + (int) Math.floor( month / 12 );\n      int newmonth = month % 12;\n\n      cal.set( newyear, newmonth, 1 );\n      int newday = cal.getActualMaximum( Calendar.DAY_OF_MONTH );\n      if ( newday < day ) {\n        cal.set( Calendar.DAY_OF_MONTH, newday );\n      } else {\n        cal.set( Calendar.DAY_OF_MONTH, day );\n      }\n\n      return ( cal.getTime() );\n    } else {\n      throw new KettleValueException( \"Unable to add months with a null value\" );\n    }\n\n  }\n\n  /**\n   * Returns the number of days that have elapsed between dataA and dataB.\n   *\n   * @param metaA\n   * @param dataA\n   *          The \"end date\"\n   * @param metaB\n   * @param dataB\n   *          The \"start date\"\n   * @param resultType\n   *          The \"result type\" (ms, s, mn, h, d)\n   * @return Number of days\n   * @throws KettleValueException\n   */","sourceCodeStart":1551,"sourceCodeEnd":1587,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java#L1551-L1587","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Guard the input: use an NVL/Coalesce or 'IF field A IS NULL THEN ...' step before the add-months calculation","Check dataA != null in your Java/UDF code before calling ValueDataUtil.addMonths","Fix the upstream step so the date field is populated (or explicitly set a default date)","If null propagation is desired, wrap the call in try-catch for KettleValueException and return null"],"exampleFix":"// before\nObject result = ValueDataUtil.addMonths( metaA, dataA, metaB, monthsToAdd );\n// after\nObject result = ( dataA == null ) ? null : ValueDataUtil.addMonths( metaA, dataA, metaB, monthsToAdd );","handlingStrategy":"type-guard","validationCode":"if ( dataA == null ) { return null; } // or NVL default\nif ( metaA != null && !metaA.isDate() ) throw new IllegalArgumentException( \"Field A must be a Date\" );","typeGuard":"boolean isNonNullDate( ValueMetaInterface m, Object d ) { return d != null && m != null && m.isDate(); }","tryCatchPattern":"try {\n  return ValueDataUtil.addMonths( metaA, dataA, metaB, dataB );\n} catch ( KettleValueException e ) {\n  if ( \"Unable to add months with a null value\".equals( e.getMessage() ) ) return null; // treat as null propagation\n  throw e;\n}","preventionTips":["Use NVL/Coalesce steps to give null dates a default before arithmetic","Null-check date inputs in any custom UDF/Calculator expressions","Trace null sources upstream (lookup misses, empty files) with a null-detect step"],"tags":["date","null-value","kettle"],"backgroundTag":"null-argument","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}