pentaho/pentaho-kettle · error · KettleException

AvroInput.Error.MutipleDifferentExpansions

AvroInput.Error.MutipleDifferentExpansions

Error message

AvroInput.Error.MutipleDifferentExpansions

What it means

When multiple field paths use '[*]' expansions, checkFieldPaths requires all of them to expand the SAME array/map (identical prefix up to and including '[*]'). If two paths expand different structures (e.g. $.person[*].first and $.person[*].address[*].street), the reader cannot produce a coherent cross-product row and throws this KettleException at init.

Solutions

  1. Make every '[*]' field expand the same structure: identical prefix before '[*]', e.g. all fields under '$.person[*].'.
  2. Split into two Avro Input steps / transformation branches, one per expanded array, and rejoin rows afterwards.
  3. Reindex one array (access by integer index instead of '[*]') so only one expansion remains.

Example fix

// before: different expansions in one step
$.person[*].firstName
$.person.addresses[*].street
// after: same expansion, or split steps
$.person[*].firstName
$.person[*].addresses.street
Defensive patterns

Strategy: validation

Validate before calling

// All '[*]' fields must share the same expansion prefix
String prefix(String p) { return p.substring(0, p.lastIndexOf("[*]") + 3); }
Set<String> prefixes = paths.stream()
    .filter(p -> p.contains("[*]"))
    .map(p -> prefix(p))
    .collect(Collectors.toSet());
if (prefixes.size() > 1) throw new IllegalArgumentException("Multiple different [*] expansions: " + prefixes);

Type guard

boolean consistentExpansions(java.util.List<String> paths) {
  java.util.Set<String> s = new java.util.HashSet<>();
  for (String p : paths) {
    if (p != null && p.contains("[*]")) s.add(p.substring(0, p.lastIndexOf("[*]") + 3));
  }
  return s.size() <= 1;
}

Try / catch

try {
  step.init(...);
} catch (KettleException e) {
  if (e.getMessage().contains("MutipleDifferentExpansions")) {
    // split fields into separate Avro Input steps and rerun
  } else throw e;
}

Prevention

When it happens

Trigger: Defining two or more fields whose '[*]' expansion prefixes differ, e.g. '$.a[*].x' together with '$.b[*].y', then calling init().

Common situations: Wanting to read fields from two sibling arrays of a record in one pass; schema evolution added a second array and old paths were reused.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

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

    String expansion = null;
    List<AvroInputField> normalList = new ArrayList<AvroInputField>();
    List<AvroInputField> expansionList = new ArrayList<AvroInputField>();
    for ( AvroInputField f : normalFields ) {
      String path = f.getAvroFieldName();

      if ( path != null && path.lastIndexOf( "[*]" ) >= 0 ) {

        if ( path.indexOf( "[*]" ) != path.lastIndexOf( "[*]" ) ) {
          throw new KettleException( BaseMessages.getString( PKG,
            "AvroInput.Error.PathContainsMultipleExpansions", path ) );
        }
        String pathPart = path.substring( 0, path.lastIndexOf( "[*]" ) + 3 );

        if ( expansion == null ) {
          expansion = pathPart;
        } else {
          if ( !expansion.equals( pathPart ) ) {
            throw new KettleException( BaseMessages.getString( PKG,
              "AvroInput.Error.MutipleDifferentExpansions" ) );
          }
        }

        expansionList.add( f );
      } else {
        normalList.add( f );
      }
    }

    normalFields.clear();
    for ( AvroInputField f : normalList ) {
      normalFields.add( f );
    }

    if ( expansionList.size() > 0 ) {

      List<AvroInputField> subFields = new ArrayList<AvroInputField>();

View on GitHub (pinned to f3058517a1)