{"id":"9131db60b747d74a","repo":"apache/kafka","slug":"requested-size-sizebytes-0","errorCode":null,"errorMessage":"requested size {sizeBytes}<=0","messagePattern":"requested size (.+?)<=0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/memory/SimpleMemoryPool.java","lineNumber":57,"sourceCode":"    protected final int maxSingleAllocationSize;\n    protected final AtomicLong startOfNoMemPeriod = new AtomicLong(); //nanoseconds\n    protected volatile Sensor oomTimeSensor;\n\n    public SimpleMemoryPool(long sizeInBytes, int maxSingleAllocationBytes, boolean strict, Sensor oomPeriodSensor) {\n        if (sizeInBytes <= 0 || maxSingleAllocationBytes <= 0 || maxSingleAllocationBytes > sizeInBytes)\n            throw new IllegalArgumentException(\"must provide a positive size and max single allocation size smaller than size.\"\n                + \"provided \" + sizeInBytes + \" and \" + maxSingleAllocationBytes + \" respectively\");\n        this.sizeBytes = sizeInBytes;\n        this.strict = strict;\n        this.availableMemory = new AtomicLong(sizeInBytes);\n        this.maxSingleAllocationSize = maxSingleAllocationBytes;\n        this.oomTimeSensor = oomPeriodSensor;\n    }\n\n    @Override\n    public ByteBuffer tryAllocate(int sizeBytes) {\n        if (sizeBytes < 1)\n            throw new IllegalArgumentException(\"requested size \" + sizeBytes + \"<=0\");\n        if (sizeBytes > maxSingleAllocationSize)\n            throw new IllegalArgumentException(\"requested size \" + sizeBytes + \" is larger than maxSingleAllocationSize \" + maxSingleAllocationSize);\n\n        long available;\n        boolean success = false;\n        //in strict mode we will only allocate memory if we have at least the size required.\n        //in non-strict mode we will allocate memory if we have _any_ memory available (so available memory\n        //can dip into the negative and max allocated memory would be sizeBytes + maxSingleAllocationSize)\n        long threshold = strict ? sizeBytes : 1;\n        while ((available = availableMemory.get()) >= threshold) {\n            success = availableMemory.compareAndSet(available, available - sizeBytes);\n            if (success)\n                break;\n        }\n\n        if (success) {\n            maybeRecordEndOfDrySpell();\n        } else {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/memory/SimpleMemoryPool.java#L39-L75","documentation":"Thrown by SimpleMemoryPool.tryAllocate(int sizeBytes) when the requested allocation size is less than 1. The pool refuses zero- or negative-length buffers because they would corrupt the available-memory accounting (the AtomicLong is decremented by sizeBytes on success). It is an IllegalArgumentException raised before any CAS on the pool counter.","triggerScenarios":"Calling tryAllocate(n) where n <= 0 — most often reached transitively when a record batch, send buffer, or request size is computed as zero or negative and handed to the memory pool. In the producer path this can occur when a Serializers/CompressionType produces an empty payload or when a caller computes a size as (a - b) that goes negative under load.","commonSituations":"A record with an empty value and an empty key combined with a compressor that writes a zero-byte payload; an arithmetic underflow producing a negative size (e.g. size = total - overhead where overhead > total); test code that pre-sizes a buffer from an uninitialized int default of 0; a custom protocol layer that calls tryAllocate(0) as a 'no-op' placeholder; an off-by-one when subtracting record-batch overhead.","solutions":["Inspect the sizeBytes value in the message — if it is 0 or negative, find the caller that computed it and fix the sizing logic.","Guard the call site: if a payload can legitimately be empty, short-circuit before tryAllocate rather than allocating a zero-length buffer.","Audit the size computation (e.g. Records.LOG_OVERHEAD, record-batch header, compression overhead) for underflow when individual components are zero.","Reproduce with producer logging at TRACE to capture the request that produced the bad size; look for record/compression-size calculation around the call.","If you maintain a custom MemoryPool, ensure tryAllocate callers never pass sizes derived from unchecked user input."],"exampleFix":"// before — computed size can go to zero/negative\nint size = payload.length - HEADER_SIZE;\nByteBuffer buf = pool.tryAllocate(size);   // throws if payload smaller than HEADER_SIZE\n\n// after — validate before allocating\nint size = Math.max(payload.length - HEADER_SIZE, 1);\nif (payload.length < HEADER_SIZE) {\n    throw new IllegalArgumentException(\"payload \" + payload.length + \" smaller than header \" + HEADER_SIZE);\n}\nByteBuffer buf = pool.tryAllocate(size);","handlingStrategy":"validation","validationCode":"// Guard tryAllocate against non-positive sizes before calling.\nint sizeBytes = ...;\nif (sizeBytes < 1) {\n    throw new IllegalArgumentException(\"Cannot allocate \" + sizeBytes + \" bytes; size must be >= 1\");\n}\nByteBuffer buf = pool.tryAllocate(sizeBytes);","typeGuard":"// Treat only positive ints as valid allocation requests.\nstatic boolean isAllocatableSize(int sizeBytes) {\n    return sizeBytes > 0;\n}","tryCatchPattern":"try {\n    buf = pool.tryAllocate(sizeBytes);\n} catch (IllegalArgumentException e) {\n    // caller passed garbage — drop the request, do not retry with the same size.\n    log.warn(\"Rejected allocation of {} bytes\", sizeBytes);\n    buf = null;\n}","preventionTips":["Coerce message sizes through a serializer/partitioner that guarantees a positive length before pooling.","Reject zero-length payloads at the application boundary rather than relying on the pool to complain.","If computing size from a serialized payload, sanity-check the result (>0, not Integer.MAX_VALUE) before allocating.","Never call tryAllocate with a value derived from an untrusted int without first bounding it."],"tags":["kafka-clients","memory-pool","producer","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}