{"id":"4c9f226935a5d928","repo":"apache/kafka","slug":"error-writing-field-name-detail","errorCode":null,"errorMessage":"Error writing field '${name}': ${detail}","messagePattern":"Error writing field '(.+?)': (.+?)","errorType":"exception","errorClass":"SchemaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/protocol/types/Schema.java","lineNumber":86,"sourceCode":"            this.fieldsByName.put(def.name, this.fields[i]);\n        }\n        //6 schemas have no fields at the time of this writing (3 versions each of list_groups and api_versions)\n        //for such schemas there's no point in even creating a unique Struct object when deserializing.\n        this.cachedStruct = this.fields.length > 0 ? null : new Struct(this, NO_VALUES);\n    }\n\n    /**\n     * Write a struct to the buffer\n     */\n    @Override\n    public void write(ByteBuffer buffer, Object o) {\n        Struct r = (Struct) o;\n        for (BoundField field : fields) {\n            try {\n                Object value = field.def.type.validate(r.get(field));\n                field.def.type.write(buffer, value);\n            } catch (Exception e) {\n                throw new SchemaException(\"Error writing field '\" + field.def.name + \"': \" +\n                                          (e.getMessage() == null ? e.getClass().getName() : e.getMessage()));\n            }\n        }\n    }\n\n    /**\n     * Read a struct from the buffer. If this schema is configured to tolerate missing\n     * optional fields at the end of the buffer, these fields are replaced with their default\n     * values; otherwise, if the schema does not tolerate missing fields, or if missing fields\n     * don't have a default value, a {@code SchemaException} is thrown to signify that mandatory\n     * fields are missing.\n     */\n    @Override\n    public Struct read(ByteBuffer buffer) {\n        if (cachedStruct != null) {\n            return cachedStruct;\n        }\n        Object[] objects = new Object[fields.length];","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/protocol/types/Schema.java#L68-L104","documentation":"Thrown by Schema.write when a field's Type.write or Type.validate raises any exception while serializing a Struct. The library wraps the cause's message (or class name if null) so the failing field is identifiable. It signals bad data being handed to the serializer rather than wire-level corruption.","triggerScenarios":"Schema.write loops over BoundFields; for each it calls field.def.type.validate(r.get(field)) then type.write(buffer, value). A ClassCastException (wrong Java type in the Struct), NullPointerException (null for a non-nullable type), or anything thrown by a nested Type (e.g. STRING/INT32/ArrayOf) lands here.","commonSituations":"Putting a Long into an INT32 field, a String into a BYTES field, null into a non-nullable type, or an Object[] of the wrong component type into an ArrayOf; building a Struct by name with a typo so a field stays unset; refactoring a Struct's field types without updating call sites.","solutions":["Inspect the named field in the exception; confirm the Struct holds a Java value matching the field's Type (INT32=Integer, INT64=Long, STRING=String, BYTES=byte[]/ByteBuffer, ARRAY=Object[]).","Ensure required/non-nullable fields are populated before write; use Struct.set with the correct BoundField handle, not a String lookup typo.","Add a Struct.validate(...) call in tests before serialization to surface type errors earlier with a clearer message.","If a field type changed, regenerate message classes (./gradlew processMessages) and rebuild against the updated Schema."],"exampleFix":"// before - wrong java type for an INT32 field\nstruct.set(\"timeout_ms\", 30000L);\n\n// after\nstruct.set(\"timeout_ms\", Integer.valueOf(30000));","handlingStrategy":"validation","validationCode":"// Validate every field BEFORE Schema.write so you fail with a clear error\n// instead of the library's wrapped \"Error writing field\" SchemaException.\nStruct r = ...; // the struct you are about to serialize\nfor (BoundField f : schema.fields()) {\n    Object v = r.get(f);\n    if (v == null && !f.def.type.isNullable()) {\n        throw new IllegalArgumentException(\n            \"Field '\" + f.def.name + \"' is null but its type is non-nullable\");\n    }\n    f.def.type.validate(v); // throws SchemaException with field-specific reason\n}\nschema.write(buffer, r);","typeGuard":"// Narrow to Struct and ensure each field matches its declared Type before write.\nstatic boolean isWriteableStruct(Object o, Schema schema) {\n    if (!(o instanceof Struct)) return false;\n    Struct s = (Struct) o;\n    for (BoundField f : schema.fields()) {\n        Object v = s.get(f);\n        if (v == null) { if (!f.def.type.isNullable()) return false; continue; }\n        try { f.def.type.validate(v); } catch (Exception e) { return false; }\n    }\n    return true;\n}","tryCatchPattern":"try {\n    schema.write(buffer, struct);\n} catch (org.apache.kafka.common.protocol.types.SchemaException e) {\n    if (e.getMessage().startsWith(\"Error writing field '\")) {\n        // 'detail' suffix is the underlying cause (often null on non-nullable,\n        // wrong type, or index out of bounds). Re-validate the named field.\n        throw new SerializationPrecheckFailedException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Always populate non-nullable fields when building the Struct; null on a non-nullable Type is the most common trigger.","Run schema.validate(struct) (or per-field type.validate) before write to surface errors with field names you control.","Construct Structs via the generated factories/builder rather than set(name, value) to get compile-time field matching.","Keep the value's Java type aligned with the declared Type (e.g. byte[] for BYTES, Long for INT64)."],"tags":["protocol","serialization","schema","type-mismatch","kafka-clients"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}