pentaho/pentaho-kettle · error · JsonInputException

JsonInput.Error.BadStructure

JsonInput.Error.BadStructure

Error message

JsonInput.Error.BadStructure

What it means

JsonInputException with message key JsonInput.Error.BadStructure thrown by FastJsonReader.evalCombinedResult when two JSONPath expressions return result lists of different sizes, meaning the JSON structure is inconsistent with the configured parallel field paths. The message includes the mismatched sizes and the two offending paths.

Solutions

  1. Align all configured field paths so each wildcard path matches the same array: use a common root like $.items[*].name and $.items[*].id.
  2. Inspect the source JSON and confirm all mapped arrays have the same length at the same nesting level.
  3. Enable 'Ignore missing path' only if genuinely optional — it does not fix size mismatches, only missing/null paths.
  4. If the source schema changed, update the paths or normalize the JSON upstream with a transformation.
  5. Add a JSONPath assertion pre-check (e.g. with Jayway JsonPath) to verify equal result sizes before running the step.

Example fix

// before: mismatched paths
$.items[*].name  (10 results)
$.details[*].id  (7 results)
// after: aligned under one array
$.items[*].name
$.items[*].id
Defensive patterns

Strategy: validation

Validate before calling

// pre-check that all mapped JSONPath arrays have equal size
Configuration cfg = Configuration.defaultConfiguration();
DocumentContext ctx = JsonPath.parse(json);
int size = -1;
for (String p : paths) {
  int n = ctx.read(p, new TypeRef<List<Object>>(){}).size();
  if (size > 0 && n != size) throw new IllegalStateException("Path " + p + " size " + n + " != " + size);
  size = n;
}

Try / catch

try { runTransformation(); }
catch (KettleException e) {
  if (e.getMessage() != null && e.getMessage().contains("BadStructure")) {
    // log the two offending paths from the message and realign field config
  } else throw e;
}

Prevention

When it happens

Trigger: evalCombinedResult: for JsonPath path i, result.size() != lastSize while lastSize > 0 and result non-empty — i.e. field paths expected to yield parallel arrays (e.g. $.a[*] with 10 matches vs $.b[*] with 7 matches) within one input object.

Common situations: Configuring several wildcard paths ($.items[*].name, $.items[*].id) against JSON where one array is shorter or nested differently; schema drift from an API version change; optional arrays missing elements; wrong wildcard depth ($..id vs $.items[*].id).

Related errors


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

Appendix: source

Thrown at plugins/json/core/src/main/java/org/pentaho/di/trans/steps/jsoninput/reader/FastJsonReader.java:245

      // built at ctor
      return true;
    }

    @Override
    public void clear() {
      results.clear();
    }
  }

  private List<List<?>> evalCombinedResult() throws JsonInputException {
    int lastSize = -1;
    String prevPath = null;
    List<List<?>> results = new ArrayList<>( compiledJsonPaths.length );
    int i = 0;
    for ( JsonPath path : compiledJsonPaths ) {
      List<Object> result = getReadContext().read( path );
      if ( result.size() != lastSize && lastSize > 0 && !result.isEmpty() ) {
        throw new JsonInputException( BaseMessages.getString(
          PKG, "JsonInput.Error.BadStructure", result.size(), inputFields[ i ].getPath(), prevPath, lastSize ) );
      }
      if ( !isIgnoreMissingPath() && ( isAllNull( result ) || result.isEmpty() ) ) {
        throw new JsonInputException(
          BaseMessages.getString( PKG, "JsonReader.Error.CanNotFindPath", inputFields[ i ].getPath() ) );
      }
      results.add( result );
      lastSize = result.size();
      prevPath = inputFields[ i ].getPath();
      i++;
    }
    return results;
  }

  public static boolean isAllNull( Iterable<?> list ) {
    for ( Object obj : list ) {
      if ( obj != null ) {
        return false;

View on GitHub (pinned to f3058517a1)