pentaho/pentaho-kettle · error · KettleException

AvroInput.Error.MalformedPathRecord

Error message

AvroInput.Error.MalformedPathRecord

What it means

Kettle exception thrown by AvroNestedReader.convertToKettleValue when the AvroInput field's path part list is exhausted while still trying to convert a record value. It means the configured read path did not correspond to the record structure being processed — no further path segment exists to navigate into the record. The path is malformed relative to the Avro record's schema.

Solutions

  1. Extend the field's path so it fully traverses the nested record down to a primitive/leaf field (e.g. 'myrecord.fieldName').
  2. Check the configured path against the actual Avro schema nesting; each record level needs one additional dot-separated part.
  3. If the path was truncated by escaping issues, verify special characters (dots inside field names) are handled correctly.
  4. Re-read the schema via the step's field discovery UI to regenerate the correct path.

Example fix

// before
Field path: order                     // stops on a record
// after
Field path: order.customer_id         // traverses into the record
Defensive patterns

Strategy: validation

Validate before calling

// Before running the transformation, verify each field path resolves to a leaf in the schema
if (!pathContainsLeafField(avroSchema, fieldPath)) {
  throw new IllegalArgumentException("Path '" + fieldPath + "' does not reach a leaf field; extend it through the record");
}

Try / catch

// Wrap conversion per field so one bad path doesn't kill the whole transformation
try {
  value = reader.convertToKettleValue(record, schema, field);
} catch (KettleException e) {
  if (e.getMessage().contains("MalformedPathRecord")) {
    logError("Path for field '" + field.getFieldName() + "' stops at a record; extend the path", e);
  }
}

Prevention

When it happens

Trigger: convertToKettleValue is called (directly or recursively from setKettleFields) with an AvroInputField whose tempParts list is empty after the value was resolved to a record — i.e. the path string was shorter than the actual nesting depth of the data, or the record was reached with no remaining path parts to select a field from.

Common situations: Users configure an Avro Input step path like 'myfield' when the data contains a nested record at that point requiring a further selector (e.g. 'myfield.innerField'); copy-pasting paths from a differently-versioned schema; paths pointing at a record without drilling into its fields.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/input/AvroNestedReader.java:637

  /**
   * Processes a record at this point in the path.
   *
   * @param record        the record to process
   * @param s             the current schema at this point in the path
   * @param ignoreMissing true if null is to be returned for user fields that don't appear in the schema
   * @return the field value or null for out-of-bounds array indexes, non-existent map keys or unsupported avro types.
   * @throws KettleException if a problem occurs
   */
  public Object convertToKettleValue(AvroInputField avroInputField, GenericData.Record record, Schema s,
                                     Schema defaultSchema, boolean ignoreMissing )
    throws KettleException {

    if ( record == null ) {
      return null;
    }

    if ( avroInputField.getTempParts().size() == 0 ) {
      throw new KettleException( BaseMessages.getString( PKG, "AvroInput.Error.MalformedPathRecord" ) );
    }

    String part = avroInputField.getTempParts().remove( 0 );
    if ( part.charAt( 0 ) == '[' ) {
      throw new KettleException(
        BaseMessages.getString( PKG, "AvroInput.Error.InvalidPath" ) + avroInputField.getTempParts() );
    }

    if ( part.indexOf( '[' ) > 0 ) {
      String arrayPart = part.substring( part.indexOf( '[' ) );
      part = part.substring( 0, part.indexOf( '[' ) );

      // put the array section back into location zero
      avroInputField.getTempParts().add( 0, arrayPart );
    }

    // part is a named field of the record
    Schema.Field fieldS = s.getField( part );

View on GitHub (pinned to f3058517a1)