{"id":"8e3ba24803f9855f","repo":"apache/kafka","slug":"array-size-size-cannot-be-negative","errorCode":null,"errorMessage":"Array size ${size} cannot be negative","messagePattern":"Array size (.+?) cannot be negative","errorType":"exception","errorClass":"SchemaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/protocol/types/ArrayOf.java","lineNumber":75,"sourceCode":"            buffer.putInt(-1);\n            return;\n        }\n\n        Object[] objs = (Object[]) o;\n        int size = objs.length;\n        buffer.putInt(size);\n\n        for (Object obj : objs)\n            type.write(buffer, obj);\n    }\n\n    @Override\n    public Object read(ByteBuffer buffer) {\n        int size = buffer.getInt();\n        if (size < 0 && isNullable())\n            return null;\n        else if (size < 0)\n            throw new SchemaException(\"Array size \" + size + \" cannot be negative\");\n\n        if (size > buffer.remaining())\n            throw new SchemaException(\"Error reading array of size \" + size + \", only \" + buffer.remaining() + \" bytes available\");\n        Object[] objs = new Object[size];\n        for (int i = 0; i < size; i++)\n            objs[i] = type.read(buffer);\n        return objs;\n    }\n\n    @Override\n    public int sizeOf(Object o) {\n        int size = 4;\n        if (o == null)\n            return size;\n\n        Object[] objs = (Object[]) o;\n        for (Object obj : objs)\n            size += type.sizeOf(obj);","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/protocol/types/ArrayOf.java#L57-L93","documentation":"Thrown by ArrayOf.read when the INT32 length prefix read from the buffer is negative on a non-nullable array. In Kafka's protocol, only nullable arrays may use the length value -1 to encode null; a non-nullable array receiving a negative length is malformed. This guard rejects corrupt or misrouted bytes before they are used to size an allocation.","triggerScenarios":"Calling Struct.read (or ArrayOf.read directly) on a ByteBuffer whose next INT32 is < 0 when the schema field was declared with `new ArrayOf(type)` rather than `ArrayOf.nullable(type)`. Also hit when a peer writes -1 as the array length for a field the local schema considers non-nullable.","commonSituations":"Broker/client version skew where one side treats an array as nullable and the other does not; a truncated or garbage ByteBuffer passed to the serializer (e.g. log corruption, wrong API key routing, misconfigured custom serialization); replaying a captured frame against the wrong Schema instance.","solutions":["Check whether the field should accept null and declare it with ArrayOf.nullable(type) instead of new ArrayOf(type).","Verify the ByteBuffer position/limit and that the bytes correspond to the Schema being read (compare API key + API version on the wire to the schema you selected).","If the bytes come from an external/recorded source, confirm the producer and consumer are on compatible client versions for the message version in use.","Hex-dump the region around the buffer position to confirm the INT32 length is what your schema expects."],"exampleFix":"// before\nnew Schema(new Field(\"topics\", new ArrayOf(STRING)))\n\n// after - allow null for an optional topic list\nnew Schema(new Field(\"topics\", ArrayOf.nullable(STRING)))","handlingStrategy":"try-catch","validationCode":"// The negative size is decoded INSIDE ArrayOf.read, so the caller cannot\n// inspect it beforehand. Only a cheap structural pre-check is possible:\nif (buffer == null || buffer.remaining() < Integer.BYTES) {\n    throw new IllegalArgumentException(\"buffer too small for array length prefix\");\n}\n// Call site still must tolerate a corrupt negative length from the wire:\nschemaType.read(buffer);","typeGuard":null,"tryCatchPattern":"try {\n    Object[] arr = (Object[]) arrayOf.read(buffer);\n} catch (org.apache.kafka.common.protocol.types.SchemaException e) {\n    // message starts with \"Array size ... cannot be negative\" -> corrupt/truncated payload\n    // or client/broker API-version skew. Drop the payload, do not retry unchanged bytes.\n    log.warn(\"Discarding malformed frame: {}\", e.getMessage());\n    throw new CorruptFrameException(e);\n}","preventionTips":["Do not hand-craft or splice raw protocol buffers; always go through the generated message read/write paths.","Keep client and broker on compatible API versions; a negative non-nullable length almost always means version skew or middlebox corruption.","Validate frame length at the network framing layer before handing the slice to the schema reader.","Never catch and continue a SchemaException as if the buffer is still usable; its position is now indeterminate."],"tags":["protocol","serialization","schema","kafka-clients"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}