apache/pulsar · error · IllegalArgumentException
JSON Record Builder doesn't support non-JSON record as a fie
Error message
JSON Record Builder doesn't support non-JSON record as a field
What it means
JsonRecordBuilderImpl.set(String, Object) accepts nested GenericRecord values only if they are GenericJsonRecord instances. Any other GenericRecord implementation (e.g. GenericAvroRecord) cannot be converted into a JSON node, so IllegalArgumentException is thrown.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/generic/JsonRecordBuilderImpl.java:49
private final GenericSchemaImpl genericSchema;
private Map<String, Object> map = new HashMap<>();
public JsonRecordBuilderImpl(GenericSchemaImpl genericSchema) {
this.genericSchema = genericSchema;
}
/**
* Sets the value of a field.
*
* @param fieldName the name of the field to set.
* @param value the value to set.
* @return a reference to the RecordBuilder.
*/
@Override
public GenericRecordBuilder set(String fieldName, Object value) {
if (value instanceof GenericRecord) {
if (!(value instanceof GenericJsonRecord)) {
throw new IllegalArgumentException("JSON Record Builder doesn't support non-JSON record as a field");
}
GenericJsonRecord genericJsonRecord = (GenericJsonRecord) value;
value = genericJsonRecord.getJsonNode();
}
map.put(fieldName, value);
return this;
}
/**
* Sets the value of a field.
*
* @param field the field to set.
* @param value the value to set.
* @return a reference to the RecordBuilder.
*/
@Override
public GenericRecordBuilder set(Field field, Object value) {View on GitHub (pinned to 820761864e)
Solutions
- Convert the Avro record to a JsonNode first (e.g. via Avro's datum writer to JSON encoding) before setting
- Use GenericJsonRecord values for nested fields in JSON record builders
- Ensure the nested field's schema type matches the parent's (JSON parent -> JSON child)
- Decode the source topic with a JSON generic schema if the target builder is JSON
Example fix
// before
jsonBuilder.set("nested", genericAvroRecord); // IllegalArgumentException
// after
JsonNode node = avroToJsonNode(genericAvroRecord);
jsonBuilder.set("nested", node); Defensive patterns
Strategy: type-guard
Validate before calling
if (value instanceof GenericRecord && !(value instanceof GenericJsonRecord)) {
throw new IllegalArgumentException("Convert nested record to GenericJsonRecord/JsonNode before setting on a JSON builder");
} Type guard
boolean canSetOnJsonBuilder(Object v) {
return !(v instanceof GenericRecord) || v instanceof GenericJsonRecord;
} Try / catch
try {
jsonBuilder.set(fieldName, value);
} catch (IllegalArgumentException e) {
jsonBuilder.set(fieldName, ((GenericAvroRecord) value).getAvroRecord().toString()); // or proper Avro->JsonNode conversion
} Prevention
- Decode nested fields with GenericJsonSchema when building JSON records
- Convert Avro records to JsonNode before JSON field assignment
- Avoid sharing field-building code between Avro and JSON pipelines without conversion
- Add tests covering nested records for every schema backend you use
When it happens
Trigger: Calling the JSON record builder's set(fieldName, value) with a value that is a GenericRecord but not GenericJsonRecord — typically a GenericAvroRecord from an Avro-schema topic.
Common situations: Copying a field read from an AVRO topic into a JSON-schema message; mixing generic schema backends when aggregating records from multiple topics; refactored code that changed the topic's schema type from AVRO to JSON without changing field construction.
Related errors
- Avro Record Builder doesn't support non-avro record as a fie
- Topic %s has an incorrect schema Info
- RestException(conversionError)
- Can not enable for all producers but denies for replicators,
- Failed to add schema to an active topic with empty(BYTES) sc
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/1e82fbcb3dbb38f3.
Report an issue: GitHub.