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
- Convert the field to String in a preceding step (Select values -> metadata type String, or use 'Get fields' / User Defined Java Expression)
- Or switch the step's source format from 'From JSON field' to building the document from stream fields
- 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
- Set the JSON field's metadata type to String in an upstream Select Values step
- Prefer building documents from fields over raw JSON when types vary
- Preview the stream in Spoon and check field types before running
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
- BaseStep.SafeMode.Exception.MixingTypes
- DynamicSQLRow.Exception.TemplateReturnDataTypeError
- Function MOD only works with numeric data
- Function NUM2STR only works on Numbers and Integers
- Function POWER only works with numeric data
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)