pentaho/pentaho-kettle · error · KettleStepException

ElasticSearchBulk.Error.NoJsonFieldFormat

ElasticSearchBulk.Error.NoJsonFieldFormat

Error message

ElasticSearchBulk.Error.NoJsonFieldFormat

What it means

In ElasticSearchBulk.addSourceFromJsonString(), when the step is configured to take the document source from a JSON field, the field value must be a String or byte[]. Any other Java type (e.g. Integer, BigDecimal, Date) cannot be used as the raw JSON source, so a KettleStepException with key 'ElasticSearchBulk.Error.NoJsonFieldFormat' is thrown.

Solutions

  1. Convert the field to String in a preceding step (Select values -> metadata type String, or use 'Get fields' / User Defined Java Expression)
  2. Or switch the step's source format from 'From JSON field' to building the document from stream fields
  3. Check the field mapping in the step dialog points at the actual JSON string field

Example fix

// before: field 'payload' typed as Number feeds the JSON source field
// after: force String upstream
// Select Values: payload -> String, or in a UDJC/Script:
row.payload = row.payload == null ? null : row.payload.toString();
Defensive patterns

Strategy: type-guard

Validate before calling

// in a preceding step or User Defined Java Class:
if (!(jsonValue instanceof String) && !(jsonValue instanceof byte[])) {
  throw new IllegalStateException("JSON source field must be String or byte[], got: " + jsonValue.getClass());
}

Type guard

boolean isValidJsonSource(Object v) {
  return v instanceof String || v instanceof byte[];
}

Try / catch

try { /* index rows */ } catch (KettleStepException e) {
  if (e.getMessage() != null && e.getMessage().contains("NoJsonFieldFormat")) {
    log.error("Check the JSON field's stream type; must be String or Binary");
  }
}

Prevention

When it happens

Trigger: indexRow() -> addSourceFromJsonString() with 'json field' source format selected, and row[jsonFieldIdx] is neither byte[] nor String — typically a numeric, boolean, or Date-typed field from the stream.

Common situations: Upstream step emits a Number/Date field but the user selected 'From JSON field' instead of building the document from fields; JSON read into a typed field by a JSON input step without forcing string type.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at plugins/elasticsearch-bulk-insert/core/src/main/java/org/pentaho/di/trans/steps/elasticsearchbulk/ElasticSearchBulk.java:244

      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulkDialog.Error.NoNodesFound" ) );
    } catch ( Exception e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Log.Exception", e
              .getLocalizedMessage() ), e );
    }
  }

  /**
   * @param row
   * @param requestBuilder
   */
  private void addSourceFromJsonString( Object[] row, IndexRequestBuilder requestBuilder ) throws KettleStepException {
    Object jsonString = row[jsonFieldIdx];
    if ( jsonString instanceof byte[] ) {
      requestBuilder.setSource( (byte[]) jsonString, XContentType.JSON );
    } else if ( jsonString instanceof String ) {
      requestBuilder.setSource( (String) jsonString, XContentType.JSON );
    } else {
      throw new KettleStepException( BaseMessages.getString( "ElasticSearchBulk.Error.NoJsonFieldFormat" ) );
    }
  }

  /**
   * @param requestBuilder
   * @param rowMeta
   * @param row
   * @throws IOException
   */
  private void addSourceFromRowFields( IndexRequestBuilder requestBuilder, RowMetaInterface rowMeta, Object[] row )
          throws IOException {
    XContentBuilder jsonBuilder = XContentFactory.jsonBuilder().startObject();

    for ( int i = 0; i < rowMeta.size(); i++ ) {
      if ( idFieldIndex != null && i == idFieldIndex ) { // skip id
        continue;
      }

View on GitHub (pinned to f3058517a1)