pentaho/pentaho-kettle · error · JsonInputException

JsonReader.Error.CanNotFindPath

JsonReader.Error.CanNotFindPath

Error message

JsonReader.Error.CanNotFindPath

What it means

FastJsonReader.evalCombinedResult validates that each configured JSON path in a JsonInput field actually produced values from the parsed document. When a field's path yields an empty or all-null result and 'Ignore missing path' is disabled, the step throws JsonReader.Error.CanNotFindPath naming the offending path. It exists to fail fast when the JSON structure no longer matches the transformation's field definitions.

Solutions

  1. Set 'Ignore missing path' on the JSON Input step if missing paths are acceptable for your data.
  2. Verify and correct the field's Path in the JSON Input step (test with a sample JSON document via Preview).
  3. Check the actual JSON structure of the incoming data (log it or preview) and update paths to match the new schema.
  4. Make the path optional upstream or supply a default via a subsequent 'If field value is null' step before/instead of failing.
  5. Enable 'Do not fail on missing path' in the step settings if you are on a version where this flag exists.

Example fix

// before (step XML for the field, missing path tolerated=false)
<ignore_missing_path>N</ignore_missing_path>
// after
<ignore_missing_path>Y</ignore_missing_path>
// or fix the path in the field definition:
// before: <path>$.custumer.id</path>
// after:  <path>$.customer.id</path>
Defensive patterns

Strategy: validation

Validate before calling

// Before running the transformation, sanity-check the JSON against configured paths
function pathExists(json, pathExpr) {
  try {
    const results = JSONPath({ json, path: pathExpr });
    return Array.isArray(results) && results.length > 0 && results.some(v => v != null);
  } catch { return false; }
}
// if (!pathExists(sampleJson, '$.customer.id')) alert('Path missing: $.customer.id');

Type guard

function hasResults(res) { return Array.isArray(res) && res.length > 0 && !res.every(v => v == null); }

Prevention

When it happens

Trigger: A JSON input field's path (e.g. $.customer.id) matches nothing in the source document, all matched values are null, or result is an empty list, while isIgnoreMissingPath() is false. Also triggered when combined (nested/looping) reads change size across fields (lastSize checks).

Common situations: Upstream API changed its JSON schema and a field was renamed or removed; field path typos ($.custumer.id); reading optional arrays that are sometimes absent; a source record genuinely has null for the queried node; reusing a transformation against a different endpoint version.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

    @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;
      }
    }
    return true;
  }

View on GitHub (pinned to f3058517a1)