{"record":{"id":"1e82fbcb3dbb38f3","repo":"apache/pulsar","slug":"json-record-builder-doesn-t-support-non-json-recor","errorCode":null,"errorMessage":"JSON Record Builder doesn't support non-JSON record as a field","messagePattern":"JSON Record Builder doesn't support non-JSON record as a field","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/generic/JsonRecordBuilderImpl.java","lineNumber":49,"sourceCode":"    private final GenericSchemaImpl genericSchema;\n    private Map<String, Object> map = new HashMap<>();\n\n    public JsonRecordBuilderImpl(GenericSchemaImpl genericSchema) {\n        this.genericSchema = genericSchema;\n    }\n\n    /**\n     * Sets the value of a field.\n     *\n     * @param fieldName the name of the field to set.\n     * @param value     the value to set.\n     * @return a reference to the RecordBuilder.\n     */\n    @Override\n    public GenericRecordBuilder set(String fieldName, Object value) {\n        if (value instanceof GenericRecord) {\n            if (!(value instanceof GenericJsonRecord)) {\n                throw new IllegalArgumentException(\"JSON Record Builder doesn't support non-JSON record as a field\");\n            }\n            GenericJsonRecord genericJsonRecord = (GenericJsonRecord) value;\n            value = genericJsonRecord.getJsonNode();\n        }\n\n        map.put(fieldName, value);\n        return this;\n    }\n\n    /**\n     * Sets the value of a field.\n     *\n     * @param field the field to set.\n     * @param value the value to set.\n     * @return a reference to the RecordBuilder.\n     */\n    @Override\n    public GenericRecordBuilder set(Field field, Object value) {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/generic/JsonRecordBuilderImpl.java#L31-L67","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\njsonBuilder.set(\"nested\", genericAvroRecord); // IllegalArgumentException\n// after\nJsonNode node = avroToJsonNode(genericAvroRecord);\njsonBuilder.set(\"nested\", node);","handlingStrategy":"type-guard","validationCode":"if (value instanceof GenericRecord && !(value instanceof GenericJsonRecord)) {\n    throw new IllegalArgumentException(\"Convert nested record to GenericJsonRecord/JsonNode before setting on a JSON builder\");\n}","typeGuard":"boolean canSetOnJsonBuilder(Object v) {\n    return !(v instanceof GenericRecord) || v instanceof GenericJsonRecord;\n}","tryCatchPattern":"try {\n    jsonBuilder.set(fieldName, value);\n} catch (IllegalArgumentException e) {\n    jsonBuilder.set(fieldName, ((GenericAvroRecord) value).getAvroRecord().toString()); // or proper Avro->JsonNode conversion\n}","preventionTips":["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"],"tags":["pulsar","json","schema","type-mismatch"],"backgroundTag":"avro-record-type-mismatch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}