{"id":"049d46794e4bad8d","repo":"apache/kafka","slug":"invalid-partition-given-with-record-partition","errorCode":null,"errorMessage":"Invalid partition given with record: ${partition} is not in the range [0...${numPartitions}].","messagePattern":"Invalid partition given with record: (.+?) is not in the range \\[0\\.\\.\\.(.+?)\\]\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java","lineNumber":641,"sourceCode":"            completion.complete(e);\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * computes partition for given record.\n     */\n    private int partition(ProducerRecord<K, V> record, Cluster cluster) {\n        Integer partition = record.partition();\n        String topic = record.topic();\n        if (partition != null) {\n            List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);\n            int numPartitions = partitions.size();\n            // they have given us a partition, use it\n            if (partition < 0 || partition >= numPartitions)\n                throw new IllegalArgumentException(\"Invalid partition given with record: \" + partition\n                                                   + \" is not in the range [0...\"\n                                                   + numPartitions\n                                                   + \"].\");\n            return partition;\n        }\n        byte[] keyBytes = keySerializer.serialize(topic, record.headers(), record.key());\n        byte[] valueBytes = valueSerializer.serialize(topic, record.headers(), record.value());\n        if (partitioner == null) {\n            return this.cluster.partitionsForTopic(record.topic()).get(0).partition();\n        }\n        return this.partitioner.partition(topic, record.key(), keyBytes, record.value(), valueBytes, cluster);\n    }\n\n    private static class Completion {\n        private final long offset;\n        private final RecordMetadata metadata;\n        private final ProduceRequestResult result;\n        private final Callback callback;","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java#L623-L659","documentation":"Thrown by MockProducer.partition(ProducerRecord, Cluster) as an IllegalArgumentException when a ProducerRecord carries an explicit partition index that is not within [0, numPartitions) for the topic as known to the mock's Cluster. The mock computes the partition only when the record already specifies one (record.partition() != null); if it is negative or >= the topic's partition count from cluster.partitionsForTopic(topic).size(), the throw fires at line 641. It mirrors the real producer's validation so partition-targeting bugs surface in tests.","triggerScenarios":"Sending a ProducerRecord constructed with an explicit partition (e.g. new ProducerRecord<>(topic, partition, key, value)) where partition < 0 or partition >= number of partitions the mock's Cluster reports for that topic. The mock Cluster defaults to Cluster.empty() (zero partitions for every topic) unless a Cluster with partition metadata was supplied to the constructor.","commonSituations":"Using the default no-arg MockProducer() (Cluster.empty()) and sending a record with an explicit partition — there are zero partitions so any index is out of range; a test that hardcodes partition=2 against a cluster mock with fewer partitions; a topic-partition count change in production metadata not reflected in the mock cluster setup.","solutions":["If you send records with explicit partitions, construct the MockProducer with a Cluster that advertises enough partitions for the topic (use Cluster.empty().append(...) or a helper that builds PartitionInfo).","If you do not need a specific partition, build ProducerRecord without the partition argument and let the partitioner/round-robin pick one.","Validate the partition against the cluster's partition count in production code before sending, surfacing the mismatch as a recoverable error.","Update the mock's Cluster setup whenever the real topic's partition count changes so the test reflects production."],"exampleFix":"// before\nMockProducer<String,String> p = new MockProducer<>(); // Cluster.empty()\np.send(new ProducerRecord<>(\"orders\", 1, k, v)); // IllegalArgumentException\n\n// after\nCluster c = Cluster.empty().withPartitions(\n    Map.of(new TopicPartition(\"orders\", 0), null,\n           new TopicPartition(\"orders\", 1), null));\nMockProducer<String,String> p = new MockProducer<>(c, true, null, new StringSerializer(), new StringSerializer());\np.send(new ProducerRecord<>(\"orders\", 1, k, v));","handlingStrategy":"validation","validationCode":"import org.apache.kafka.common.PartitionInfo;\nimport java.util.List;\n\nvoid safeSend(MockProducer<K,V> p, ProducerRecord<K,V> r) {\n    Integer part = r.partition();\n    if (part != null) {\n        List<PartitionInfo> parts = p.partitionsFor(r.topic());\n        int n = parts == null ? 0 : parts.size();\n        if (part < 0 || part >= n) {\n            throw new IllegalArgumentException(\n                \"Refusing send: partition \" + part + \" out of [0..\" + n + \")\");\n        }\n    }\n    p.send(r);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If you set ProducerRecord.partition(), always validate it against the current cluster metadata before send.","Prefer letting the partitioner choose; only pin a partition when you have authoritative knowledge of partition count.","Refresh and cache partitionsFor(topic) when topics are created/expanded; stale counts cause this error.","In tests, configure the MockProducer's Cluster with the exact partition count you intend to use."],"tags":["mock-producer","partitioning","cluster-metadata","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}