{"record":{"id":"7e8a27b06e991c8b","repo":"pentaho/pentaho-kettle","slug":"dimensionlookup-exception-nulldimensionupdateddate","errorCode":null,"errorMessage":"DimensionLookup.Exception.NullDimensionUpdatedDate","messagePattern":"DimensionLookup\\.Exception\\.NullDimensionUpdatedDate","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/dimensionlookup/DimensionLookup.java","lineNumber":255,"sourceCode":"    return true;\n  }\n\n  private Date determineDimensionUpdatedDate( Object[] row ) throws KettleException {\n    if ( data.datefieldnr < 0 ) {\n      return getTrans().getCurrentDate(); // start of transformation...\n    } else {\n      Date rtn = data.inputRowMeta.getDate( row, data.datefieldnr ); // Date field in the input row\n      if ( rtn != null ) {\n        return rtn;\n      } else {\n        // Fix for PDI-4816\n        String inputRowMetaStringMeta = null;\n        try {\n          inputRowMetaStringMeta = data.inputRowMeta.toStringMeta();\n        } catch ( Exception ex ) {\n          inputRowMetaStringMeta = \"No row input meta\";\n        }\n        throw new KettleStepException( BaseMessages.getString(\n          PKG, \"DimensionLookup.Exception.NullDimensionUpdatedDate\", inputRowMetaStringMeta ) );\n      }\n    }\n  }\n\n  /**\n   * Pre-load the cache by reading the whole dimension table from disk...\n   *\n   * @throws KettleException in case there is a database or cache problem.\n   */\n  private void preloadCache() throws KettleException {\n    try {\n      DatabaseMeta databaseMeta = meta.getDatabaseMeta();\n\n      // tk, version, from, to, natural keys, retrieval fields...\n      //\n      String sql = \"SELECT \" + databaseMeta.quoteField( meta.getKeyField() );\n      // sql+=\", \"+databaseMeta.quoteField(meta.getVersionField());","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/dimensionlookup/DimensionLookup.java#L237-L273","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the dimension lookup's date range start to 'System date' so a null never occurs, or","Fix the upstream step/field so the start-date column always contains a valid Date before reaching this step","Add a 'Value Mapper'/'If field value is null' step before the Dimension Lookup to replace nulls with a default date","Verify the Date field selected in the step dialog actually matches the incoming row field name and type"],"exampleFix":"// before: start date from stream column that can be null\n// DimensionLookupMeta.creationDate = false; startDateField = \"last_seen\" (nullable)\n// after: guarantee non-null upstream\n// use 'If field value is null' step: if last_seen is null -> set to new Date(),\n// or switch date range start to 'System date' in the Dimension Lookup dialog","handlingStrategy":"validation","validationCode":"// before the transformation runs, ensure the start-date field is non-null\nif ( row.getDate(\"last_seen\") == null ) {\n  row.setDate(\"last_seen\", new java.util.Date()); // or route row to an error stream\n}","typeGuard":"boolean hasUpdateDate(Object[] row, int idx) {\n  return idx >= 0 && row[idx] instanceof java.util.Date;\n}","tryCatchPattern":"try {\n  step.processRow(row);\n} catch (KettleStepException e) {\n  if (e.getMessage().contains(\"NullDimensionUpdatedDate\")) {\n    logError(\"Row missing dimension update date; sending to error stream: \" + row);\n  } else { throw e; }\n}","preventionTips":["Prefer 'System date' as date range start when business dates aren't strictly required","Add a null-handling step (If field value is null) before the Dimension Lookup","Validate the start-date column's type is Date end-to-end, not String or Object"],"tags":["database","etl","null-value","slowly-changing-dimension"],"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"}