pentaho/pentaho-kettle · error · KettleStepException

DimensionLookup.Exception.NullDimensionUpdatedDate

Error message

DimensionLookup.Exception.NullDimensionUpdatedDate

What it means

DimensionLookup throws this when the 'last updated' date value that must be written to the dimension's date-from/last-updated column is null at processing time. The step needs a valid update date to maintain the slowly-changing-dimension history; without it it cannot record when the row was inserted/updated, so it aborts the row with a KettleStepException that includes the input row metadata string to aid debugging.

Solutions

  1. Set the dimension lookup's date range start to 'System date' so a null never occurs, or
  2. Fix the upstream step/field so the start-date column always contains a valid Date before reaching this step
  3. Add a 'Value Mapper'/'If field value is null' step before the Dimension Lookup to replace nulls with a default date
  4. Verify the Date field selected in the step dialog actually matches the incoming row field name and type

Example fix

// before: start date from stream column that can be null
// DimensionLookupMeta.creationDate = false; startDateField = "last_seen" (nullable)
// after: guarantee non-null upstream
// use 'If field value is null' step: if last_seen is null -> set to new Date(),
// or switch date range start to 'System date' in the Dimension Lookup dialog
Defensive patterns

Strategy: validation

Validate before calling

// before the transformation runs, ensure the start-date field is non-null
if ( row.getDate("last_seen") == null ) {
  row.setDate("last_seen", new java.util.Date()); // or route row to an error stream
}

Type guard

boolean hasUpdateDate(Object[] row, int idx) {
  return idx >= 0 && row[idx] instanceof java.util.Date;
}

Try / catch

try {
  step.processRow(row);
} catch (KettleStepException e) {
  if (e.getMessage().contains("NullDimensionUpdatedDate")) {
    logError("Row missing dimension update date; sending to error stream: " + row);
  } else { throw e; }
}

Prevention

When it happens

Trigger: determineDimensionUpdatedDate is called from processRow/lookupValues when the configured 'date range start' source (system date, stream column, or null) resolves to a null Date — typically the chosen start-date alternative is a column value and that field is null in the incoming row.

Common situations: The Date field selected in the Dimension Lookup dialog exists in row metadata but carries null data (upstream step produced empty value); field type changed to non-Date so getDate returns null; transformation XML hand-edited so the startDateField points at the wrong column.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/dimensionlookup/DimensionLookup.java:255

    return true;
  }

  private Date determineDimensionUpdatedDate( Object[] row ) throws KettleException {
    if ( data.datefieldnr < 0 ) {
      return getTrans().getCurrentDate(); // start of transformation...
    } else {
      Date rtn = data.inputRowMeta.getDate( row, data.datefieldnr ); // Date field in the input row
      if ( rtn != null ) {
        return rtn;
      } else {
        // Fix for PDI-4816
        String inputRowMetaStringMeta = null;
        try {
          inputRowMetaStringMeta = data.inputRowMeta.toStringMeta();
        } catch ( Exception ex ) {
          inputRowMetaStringMeta = "No row input meta";
        }
        throw new KettleStepException( BaseMessages.getString(
          PKG, "DimensionLookup.Exception.NullDimensionUpdatedDate", inputRowMetaStringMeta ) );
      }
    }
  }

  /**
   * Pre-load the cache by reading the whole dimension table from disk...
   *
   * @throws KettleException in case there is a database or cache problem.
   */
  private void preloadCache() throws KettleException {
    try {
      DatabaseMeta databaseMeta = meta.getDatabaseMeta();

      // tk, version, from, to, natural keys, retrieval fields...
      //
      String sql = "SELECT " + databaseMeta.quoteField( meta.getKeyField() );
      // sql+=", "+databaseMeta.quoteField(meta.getVersionField());

View on GitHub (pinned to f3058517a1)