{"id":"a9a89925646b017a","repo":"apache/kafka","slug":"error-reading-bytes-of-size-size-only-remain","errorCode":null,"errorMessage":"Error reading bytes of size ${size}, only ${remaining} bytes available","messagePattern":"Error reading bytes of size (.+?), only (.+?) bytes available","errorType":"exception","errorClass":"SchemaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/protocol/types/Type.java","lineNumber":132,"sourceCode":"        @Override\n        public String toString() {\n            return typeName();\n        }\n    }\n\n    public static String stringRead(ByteBuffer buffer, int length) {\n        if (length > Short.MAX_VALUE)\n            throw new SchemaException(\"String length \" + length + \" is larger than the maximum string length.\");\n        if (length > buffer.remaining())\n            throw new SchemaException(\"Error reading string of length \" + length + \", only \" + buffer.remaining() + \" bytes available\");\n        String result = Utils.utf8(buffer, length);\n        buffer.position(buffer.position() + length);\n        return result;\n    }\n\n    public static ByteBuffer bytesRead(ByteBuffer buffer, int size) {\n        if (size > buffer.remaining())\n            throw new SchemaException(\"Error reading bytes of size \" + size + \", only \" + buffer.remaining() + \" bytes available\");\n\n        int limit = buffer.limit();\n        int newPosition = buffer.position() + size;\n        buffer.limit(newPosition);\n        ByteBuffer val = buffer.slice();\n        buffer.limit(limit);\n        buffer.position(newPosition);\n        return val;\n    }\n\n    /**\n     * The Boolean type represents a boolean value in a byte by using\n     * the value of 0 to represent false, and 1 to represent true.\n     *\n     * If for some reason a value that is not 0 or 1 is read,\n     * then any non-zero value will return true.\n     */\n    public static final DocumentedType BOOLEAN = new DocumentedType() {","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/protocol/types/Type.java#L114-L150","documentation":"Thrown by bytesRead() when the BYTES field's declared size is positive but larger than buffer.remaining(). This is the truncated-frame guard for the raw-byte schema type and is raised as a SchemaException before slicing the buffer. It protects against underflow and malformed length prefixes during Kafka protocol decoding.","triggerScenarios":"BYTES.read(buffer) or COMPACT_BYTES.read(buffer) calling bytesRead(buffer, size) where size > buffer.remaining(). Hit during ApiMessage/Struct deserialization of any byte-array field (e.g. record batches, SASL tokens, serialized values) when the source buffer is short.","commonSituations":"Partial network read passed to the decoder. Buffer position corrupted by an earlier mis-sized field. Client/broker version mismatch changing a field's encoding. A proxy or custom serializer emitting an incorrect length prefix.","solutions":["Confirm the complete response frame has been read off the socket before invoking the schema decoder.","Log size vs buffer.remaining() at the failure point to confirm truncation vs schema drift.","Check for an earlier field whose wrong length shifted the position (decode field-by-field in DEBUG).","Align client and broker versions for the API key in the failing exchange."],"exampleFix":"// before: decoding before the frame is fully buffered\nByteBuffer val = Type.bytesRead(buffer, size); // throws if size > remaining\n\n// after: ensure full frame presence first\nif (buffer.remaining() < size) {\n    throw new IllegalStateException(\"Incomplete frame: need \" + size\n        + \" bytes, have \" + buffer.remaining());\n}\nByteBuffer val = buffer.slice();","handlingStrategy":"validation","validationCode":"// bytesRead(buffer, size) is public and takes size as a param.\nif (size > buffer.remaining()) {\n    throw new IllegalArgumentException(\n        \"Need \" + size + \" bytes but only \" + buffer.remaining() + \" available\");\n}\njava.nio.ByteBuffer value = org.apache.kafka.common.protocol.types.Type.bytesRead(buffer, size);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["bytesRead is a public static helper — check size <= buffer.remaining() before invoking it.","Reassemble full frames at the transport layer before handing them to the protocol deserializer so remaining() is always authoritative.","Log the declared size vs. remaining() on failure; a recurring mismatch indicates a framing bug upstream."],"tags":["protocol","serialization","schema","bytes","truncation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}