ManualPartitionSubscription does partition assignment updates in the wrong order. It calls KafkaConsumer.assign, then onPartitionsRevoked and last onPartitionsAssigned. The order should be onPartitionsRevoked, then assign, then onPartitionsAssigned.
onPartitionsRevoked has to be called before we reassign partitions, because we try to commit offsets for the revoked partitions. If we try to commit to a partition the consumer is not assigned, it will throw an exception. The onRevoke, assign, onAssign order is also more in line with the javadoc for ConsumerRebalanceListener, which specifies that onRevoke should be called before the partition rebalance begins.