{"id":"9cef11019208d15d","repo":"apache/kafka","slug":"must-provide-a-positive-size-and-max-single-alloca","errorCode":null,"errorMessage":"must provide a positive size and max single allocation size smaller than size.provided {sizeInBytes} and {maxSingleAllocationBytes} respectively","messagePattern":"must provide a positive size and max single allocation size smaller than size\\.provided (.+?) and (.+?) respectively","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/memory/SimpleMemoryPool.java","lineNumber":45,"sourceCode":"\n\n/**\n * a simple pool implementation. this implementation just provides a limit on the total outstanding memory.\n * any buffer allocated must be release()ed always otherwise memory is not marked as reclaimed (and \"leak\"s)\n */\npublic class SimpleMemoryPool implements MemoryPool {\n    protected final Logger log = LoggerFactory.getLogger(getClass()); //subclass-friendly\n\n    protected final long sizeBytes;\n    protected final boolean strict;\n    protected final AtomicLong availableMemory;\n    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.","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/memory/SimpleMemoryPool.java#L27-L63","documentation":"Thrown by the SimpleMemoryPool constructor when its invariants are violated: sizeInBytes and maxSingleAllocationBytes must both be positive and the single-allocation cap must not exceed the pool size. This guards the Send/NetworkClient buffer pools (and any other MemoryPool consumer) against a misconfiguration that would make the pool unable to satisfy even a single allocation. It is an IllegalArgumentException raised at construction, before any traffic flows.","triggerScenarios":"Instantiating new SimpleMemoryPool(sizeInBytes, maxSingleAllocationBytes, strict, sensor) where sizeInBytes<=0, maxSingleAllocationBytes<=0, or maxSingleAllocationBytes>sizeInBytes. Also raised when a subclass (e.g. GarbageCollectedMemoryPool) calls super(...) with computed values that go non-positive. In Kafka itself this constructor is reached through ProducerConfig (buffer.memory / batch.size) or broker send-buffer pool wiring on startup.","commonSituations":"Setting `buffer.memory` or `batch.size` to 0 or negative in producer/broker config; mis-parsing a memory string (e.g. dropping the unit suffix so '64' is read as bytes); a custom MemoryPool subclass passing computed maxSingleAllocationBytes that ends up larger than the total pool; running a test harness that injects a tiny pool size and a batch size larger than it; misconfigured `socket.request.max.bytes` exceeding `buffer.memory`.","solutions":["Inspect the two numbers in the exception message and confirm both are positive and that maxSingleAllocationBytes <= sizeInBytes.","Check `buffer.memory` (default 32 MiB) and `batch.size` (default 16 KiB) in your producer/broker config; ensure batch.size < buffer.memory and neither is 0 or negative.","If configuring the pool programmatically, add an assert or Objects.checkIndex / requirePositive guard at the call site so bad values are caught at the source.","Validate memory-string parsing in your config layer — make sure values like '32MB' are decoded into the correct byte count, not silently truncated.","For test code, size the pool at least as large as the largest single allocation you intend to make (typically >= batch.size)."],"exampleFix":"// before — batch larger than the whole pool throws\nprops.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 16L * 1024); // 16 KiB\nprops.put(ProducerConfig.BATCH_SIZE_CONFIG, 64 * 1024);     // 64 KiB\nProducer<String,String> p = new KafkaProducer<>(props);    // SimpleMemoryPool ctor throws\n\n// after — keep batch.size well under buffer.memory\nprops.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 32L * 1024 * 1024); // 32 MiB (default)\nprops.put(ProducerConfig.BATCH_SIZE_CONFIG,      16 * 1024);      // 16 KiB (default)","handlingStrategy":"validation","validationCode":"// Validate constructor args once, before instantiating the pool.\nlong sizeInBytes = ...;\nint maxSingleAllocationBytes = ...;\nif (sizeInBytes <= 0 || maxSingleAllocationBytes <= 0 || maxSingleAllocationBytes > sizeInBytes) {\n    throw new IllegalArgumentException(\n        \"sizeInBytes must be > 0 and maxSingleAllocationBytes must be > 0 and <= sizeInBytes\");\n}\nMemoryPool pool = new SimpleMemoryPool(sizeInBytes, maxSingleAllocationBytes, strict, sensor);","typeGuard":"// Narrow raw long/int inputs to a validated config record.\nrecord PoolConfig(long sizeBytes, int maxSingleAllocationBytes, boolean strict) {\n    PoolConfig {\n        if (sizeBytes <= 0 || maxSingleAllocationBytes <= 0 || maxSingleAllocationBytes > sizeBytes)\n            throw new IllegalArgumentException(\"Invalid pool config\");\n    }\n}","tryCatchPattern":"try {\n    pool = new SimpleMemoryPool(sizeBytes, max, strict, sensor);\n} catch (IllegalArgumentException e) {\n    // misconfiguration — fail fast at startup with the user-facing message.\n    failStartup(\"Bad memory pool configuration: \" + e.getMessage());\n}","preventionTips":["Treat pool sizing as startup configuration: validate once at boot, never at request time.","Keep maxSingleAllocationBytes <= sizeInBytes; a useful rule is max = sizeInBytes to start, then tune down.","Source both values from a typed config object with its own constructor guard, so invalid combinations cannot reach SimpleMemoryPool.","Use bytes (not KB/MB) and double-check units — unit confusion is the most common cause of this error."],"tags":["kafka-clients","memory-pool","producer-config","startup","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}