pentaho/pentaho-kettle · error · KettleValueException

API error. ValueMetaInterface can't be null!

Error message

API error. ValueMetaInterface can't be null!

What it means

ValueDataUtil.getZeroForValueMetaType returns the zero value (0, 0.0, BigDecimal.ZERO, "", etc.) for a given ValueMetaInterface type, and explicitly rejects a null argument with this KettleValueException as an API contract check.

Solutions

  1. Pass a non-null ValueMetaInterface — resolve the field from RowMetaInterface first and fail early if it is missing
  2. Guard the call: if ( type != null ) before invoking getZeroForValueMetaType
  3. Fix the lookup that produced null (check field names/case and step connectivity)
  4. If you only need a zero for a known type constant, construct it directly instead of via ValueMeta

Example fix

// before
Object zero = ValueDataUtil.getZeroForValueMetaType( rowMeta.getValueMeta( idx ) ); // idx out of range => null
// after
ValueMetaInterface type = idx >= 0 && idx < rowMeta.size() ? rowMeta.getValueMeta( idx ) : null;
Object zero = ( type != null ) ? ValueDataUtil.getZeroForValueMetaType( type ) : null;
Defensive patterns

Strategy: type-guard

Validate before calling

if ( type == null ) { throw new IllegalArgumentException( "ValueMetaInterface must not be null" ); }

Type guard

ValueMetaInterface requireValueMeta( ValueMetaInterface m ) { if ( m == null ) throw new IllegalArgumentException( "null ValueMeta" ); return m; }

Try / catch

try {
  return ValueDataUtil.getZeroForValueMetaType( type );
} catch ( KettleValueException e ) {
  if ( e.getMessage() != null && e.getMessage().contains( "can't be null" ) ) {
    log.error( "ValueMeta lookup produced null — check field name/step mapping" );
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling ValueDataUtil.getZeroForValueMetaType(null) — typically when a ValueMeta lookup returned null, e.g. a field was absent from the row meta or a metadata lookup failed and the null was passed straight through.

Common situations: Field removed/renamed upstream so getFieldFromRow/getValueMeta returns null; programmatically built ValueMeta objects where type resolution was skipped; plugin code assuming a field always exists in the row.

Related errors


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

Appendix: source

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

    } catch ( Exception e ) {
      throw new KettleValueException( e );
    } finally {
      IOUtils.closeQuietly( file );
    }
    return encoding;
  }

  /**
   *  Default utility method to get exact zero value according to ValueMetaInterface. Using
   *  this utility method saves from ClassCastExceptions later.
   *
   * @param type
   * @return
   * @throws KettleValueException
   */
  public static Object getZeroForValueMetaType( ValueMetaInterface type ) throws KettleValueException {
    if ( type == null ) {
      throw new KettleValueException( "API error. ValueMetaInterface can't be null!" );
    }

    switch ( type.getType() ) {
      case ( ValueMetaInterface.TYPE_INTEGER ) : {
        return new Long( 0 );
      }
      case ( ValueMetaInterface.TYPE_NUMBER ) : {
        return new Double( 0 );
      }
      case ( ValueMetaInterface.TYPE_BIGNUMBER ) : {
        return new BigDecimal( 0 );
      }
      case ( ValueMetaInterface.TYPE_STRING ) : {
        return "";
      }
      default : {
        throw new KettleValueException( "get zero function undefined for data type: " + type.getType() );
      }

View on GitHub (pinned to f3058517a1)