Error reading LocalDate stored as BSON

Hello community,
I want to read a LocalDate which is stzored as BsonDateTime in mongodb.

im using

org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3 org.mongodb:mongodb-driver-sync:4.11.2 org.mongodb:bson-kotlinx:4.11.2

therefore I created a LocalDateSerializer

package mycompany.samples.localdate

import com.github.avrokotlin.avro4k.decoder.RecordDecoder
import com.github.avrokotlin.avro4k.encoder.RecordEncoder
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonEncoder
import org.bson.BsonDateTime
import org.bson.BsonType.DATE_TIME
import org.bson.codecs.kotlinx.BsonDecoder
import org.bson.codecs.kotlinx.BsonEncoder
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset.UTC
import java.time.format.DateTimeFormatter

@OptIn(ExperimentalSerializationApi::class)
object LocalDateSerializer : KSerializer<LocalDate> {
    private val formatter = DateTimeFormatter.ISO_LOCAL_DATE

    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(javaClass.name, PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: LocalDate) {
        when (encoder) {
            is JsonEncoder -> {
                encoder.encodeString(value.format(formatter))
            }
            is RecordEncoder -> {
                encoder.encodeString(value.format(formatter))
            }
            is BsonEncoder -> {
                println("value=$value - epochMilli=${value.atStartOfDay(UTC).toInstant().toEpochMilli()}")
                encoder.encodeBsonValue(BsonDateTime(value.atStartOfDay(UTC).toInstant().toEpochMilli()))
            }
            else -> throw IllegalArgumentException("Unsupported encoder type: ${encoder::class}")
        }
    }

    override fun deserialize(decoder: Decoder): LocalDate = when (decoder) {
        is JsonDecoder -> LocalDate.parse(decoder.decodeString(), formatter)
        is RecordDecoder -> LocalDate.parse(decoder.decodeString(), formatter)
        is BsonDecoder -> decodeBsonValue(decoder)
        else -> throw throw IllegalArgumentException("Unsupported decoder type: ${decoder::class}")
    }

    private fun decodeBsonValue(decoder: BsonDecoder): LocalDate {
        val bsonValue = decoder.decodeBsonValue()
        println("bsonValue=$bsonValue")
        return if (bsonValue.bsonType == DATE_TIME) {
            val decoded = decoder.decodeBsonValue()
            println("decoded=$decoded")
            val converted = decoded as BsonDateTime
            println("converted=$converted")
            val millis = converted.value
            println("millis=$millis")
            Instant.ofEpochMilli(millis).atZone(UTC).toLocalDate()
        } else {
            throw SerializationException(
                "Deserialization of LocalDate from BSON is not supported for ${bsonValue::class.simpleName}"
            )
        }
    }
}
`

this is my Document to persist

`
package mycompany.samples.localdate

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDate

@Serializable
data class LocalDatesDocument(
    @SerialName("_id") val id: String,
    @Serializable(with = LocalDateSerializer::class)
    val simpleLocaDate: LocalDate
)
`

this is my repository

``
package mycompany.samples.localdate

import com.mongodb.MongoClientSettings
import com.mongodb.WriteConcern
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import kotlinx.serialization.ExperimentalSerializationApi
import org.bson.codecs.configuration.CodecRegistries
import org.bson.codecs.configuration.CodecRegistry
import org.bson.codecs.kotlinx.KotlinSerializerCodec

@OptIn(ExperimentalSerializationApi::class)
class LocalDatesRepository(database: MongoDatabase) {

    private val codecRegistry: CodecRegistry = CodecRegistries.fromRegistries(
        CodecRegistries.fromCodecs(
            KotlinSerializerCodec.create<LocalDatesDocument>(org.bson.codecs.kotlinx.defaultSerializersModule)
        ),
        MongoClientSettings.getDefaultCodecRegistry()
    )

    internal val collection: MongoCollection<LocalDatesDocument> = database
        .getCollection("localdates", LocalDatesDocument::class.java)
        .withWriteConcern(WriteConcern.MAJORITY)
        .withCodecRegistry(codecRegistry)

    fun findAll(): List<LocalDatesDocument> = collection.find().toList()

    fun count(): Long = collection.countDocuments()
}
`

And this is my simple integration test

`
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import java.time.LocalDate

@ExtendWith(SyncMongoExtension::class)
internal class LocalDatesRepositoryTests(private val database: MongoDatabase) {
    private val testee = LocalDatesRepository(database)
    private val collection: MongoCollection<LocalDatesDocument> = testee.collection

    @AfterEach
    fun cleanMongoDatabase() {
        database.drop()
    }

    @Test
    fun `should persist and load LocalDate objects`() {
        assertThat(testee.count()).isEqualTo(0L)

        collection.insertOne(LocalDatesDocument("1", LocalDate.of(1970, 1, 2)))

        assertThat(testee.count()).isEqualTo(1L)
        val result = testee.findAll()
        assertThat(result).containsExactlyInAnyOrder(
            LocalDatesDocument("1", LocalDate.of(1970, 1, 2))
        )
    }
}
`

But I always get this exception

`
11:52:11.757 [Test worker] INFO  org.mongodb.driver.client - MongoClient with metadata {"driver": {"name": "mongo-java-driver|sync", "version": "4.11.2"}, "os": {"type": "Darwin", "name": "Mac OS X", "architecture": "aarch64", "version": "14.7"}, "platform": "Java/BellSoft/21.0.3+10-LTS"} created with settings MongoClientSettings{readPreference=primary, writeConcern=WriteConcern{w=null, wTimeout=null ms, journal=null}, retryWrites=true, retryReads=true, readConcern=ReadConcern{level=null}, credential=null, transportSettings=null, streamFactoryFactory=null, commandListeners=[], codecRegistry=ProvidersCodecRegistry{codecProviders=[ValueCodecProvider{}, BsonValueCodecProvider{}, DBRefCodecProvider{}, DBObjectCodecProvider{}, DocumentCodecProvider{}, CollectionCodecProvider{}, IterableCodecProvider{}, MapCodecProvider{}, GeoJsonCodecProvider{}, GridFSFileCodecProvider{}, Jsr310CodecProvider{}, JsonObjectCodecProvider{}, BsonCodecProvider{}, EnumCodecProvider{}, com.mongodb.client.model.mql.ExpressionCodecProvider@725cbf49, com.mongodb.Jep395RecordCodecProvider@2d7f28de, com.mongodb.KotlinCodecProvider@74737991]}, loggerSettings=LoggerSettings{maxDocumentLength=1000}, clusterSettings={hosts=[localhost:32801], srvServiceName=mongodb, mode=SINGLE, requiredClusterType=UNKNOWN, requiredReplicaSetName='null', serverSelector='null', clusterListeners='[]', serverSelectionTimeout='30000 ms', localThreshold='15 ms'}, socketSettings=SocketSettings{connectTimeoutMS=10000, readTimeoutMS=0, receiveBufferSize=0, proxySettings=ProxySettings{host=null, port=null, username=null, password=null}}, heartbeatSocketSettings=SocketSettings{connectTimeoutMS=10000, readTimeoutMS=10000, receiveBufferSize=0, proxySettings=ProxySettings{host=null, port=null, username=null, password=null}}, connectionPoolSettings=ConnectionPoolSettings{maxSize=100, minSize=0, maxWaitTimeMS=120000, maxConnectionLifeTimeMS=0, maxConnectionIdleTimeMS=0, maintenanceInitialDelayMS=0, maintenanceFrequencyMS=60000, connectionPoolListeners=[], maxConnecting=2}, serverSettings=ServerSettings{heartbeatFrequencyMS=10000, minHeartbeatFrequencyMS=500, serverListeners='[]', serverMonitorListeners='[]'}, sslSettings=SslSettings{enabled=false, invalidHostNameAllowed=false, context=null}, applicationName='null', compressorList=[], uuidRepresentation=STANDARD, serverApi=null, autoEncryptionSettings=null, dnsClient=null, inetAddressResolver=null, contextProvider=null}
11:52:11.782 [cluster-ClusterId{value='66fd17cb93537324762dab84', description='null'}-localhost:32801] INFO  org.mongodb.driver.cluster - Monitor thread successfully connected to server with description ServerDescription{address=localhost:32801, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=21, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=28720125, setName='docker-rs', canonicalAddress=51d7dadae0fa:27017, hosts=[51d7dadae0fa:27017], passives=[], arbiters=[], primary='51d7dadae0fa:27017', tagSet=TagSet{[]}, electionId=7fffffff0000000000000001, setVersion=1, topologyVersion=TopologyVersion{processId=66fd17c8820bf8d6c767a3bb, counter=6}, lastWriteDate=Wed Oct 02 11:52:11 CEST 2024, lastUpdateTimeNanos=17160271895166}
value=1970-01-02 - epochMilli=86400000
bsonValue=BsonDateTime{value=86400000}

readDateTime can only be called when State is VALUE, not when State is END_OF_DOCUMENT.
org.bson.BsonInvalidOperationException: readDateTime can only be called when State is VALUE, not when State is END_OF_DOCUMENT.
	at org.bson.AbstractBsonReader.throwInvalidState(AbstractBsonReader.java:668)
	at org.bson.AbstractBsonReader.verifyBSONType(AbstractBsonReader.java:686)
	at org.bson.AbstractBsonReader.checkPreconditions(AbstractBsonReader.java:721)
	at org.bson.AbstractBsonReader.readDateTime(AbstractBsonReader.java:309)
	at org.bson.codecs.BsonDateTimeCodec.decode(BsonDateTimeCodec.java:31)
	at org.bson.codecs.BsonDateTimeCodec.decode(BsonDateTimeCodec.java:28)
	at org.bson.codecs.BsonValueCodec.decode(BsonValueCodec.java:55)
	at org.bson.codecs.kotlinx.DefaultBsonDecoder.decodeBsonValue(BsonDecoder.kt:180)
	at mycompany.samples.localdate.LocalDateSerializer.decodeBsonValue(LocalDateSerializer.kt:57)
	at mycompany.samples.localdate.LocalDateSerializer.deserialize(LocalDateSerializer.kt:49)
	at mycompany.samples.localdate.LocalDateSerializer.deserialize(LocalDateSerializer.kt:24)
	at kotlinx.serialization.encoding.Decoder$DefaultImpls.decodeSerializableValue(Decoding.kt:257)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:16)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
	at mycompany.samples.localdate.LocalDatesDocument$$serializer.deserialize(LocalDatesDocument.kt:7)
	at mycompany.samples.localdate.LocalDatesDocument$$serializer.deserialize(LocalDatesDocument.kt:7)
	at org.bson.codecs.kotlinx.KotlinSerializerCodec.decode(KotlinSerializerCodec.kt:182)
	at com.mongodb.internal.operation.CommandResultArrayCodec.decode(CommandResultArrayCodec.java:52)
	at com.mongodb.internal.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:60)
	at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:87)
	at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:42)
	at org.bson.internal.LazyCodec.decode(LazyCodec.java:53)
	at org.bson.codecs.BsonDocumentCodec.readValue(BsonDocumentCodec.java:104)
	at com.mongodb.internal.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:63)
	at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:87)
	at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:42)
	at com.mongodb.internal.connection.ReplyMessage.<init>(ReplyMessage.java:48)
	at com.mongodb.internal.connection.InternalStreamConnection.getCommandResult(InternalStreamConnection.java:567)
	at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:461)
	at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:372)
	at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:114)
	at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:765)
	at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:76)
	at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:209)
	at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:115)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:83)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:74)
	at com.mongodb.internal.connection.DefaultServer$OperationCountTrackingConnection.command(DefaultServer.java:299)
	at com.mongodb.internal.operation.SyncOperationHelper.createReadCommandAndExecute(SyncOperationHelper.java:273)
	at com.mongodb.internal.operation.FindOperation.lambda$execute$1(FindOperation.java:325)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$0(SyncOperationHelper.java:127)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:152)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$1(SyncOperationHelper.java:126)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:152)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:125)
	at com.mongodb.internal.operation.FindOperation.lambda$execute$2(FindOperation.java:322)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$decorateReadWithRetries$12(SyncOperationHelper.java:292)
	at com.mongodb.internal.async.function.RetryingSyncSupplier.get(RetryingSyncSupplier.java:67)
	at com.mongodb.internal.operation.FindOperation.execute(FindOperation.java:333)
	at com.mongodb.internal.operation.FindOperation.execute(FindOperation.java:73)
	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:153)
	at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:130)
	at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:90)
	at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:37)
	at kotlin.collections.CollectionsKt___CollectionsKt.toCollection(_Collections.kt:1295)
	at kotlin.collections.CollectionsKt___CollectionsKt.toMutableList(_Collections.kt:1328)
	at kotlin.collections.CollectionsKt___CollectionsKt.toList(_Collections.kt:1319)
	at mycompany.samples.localdate.LocalDatesRepository.findAll(LocalDatesRepository.kt:27)
	at mycompany.samples.localdate.LocalDatesRepositoryTests.should persist and load LocalDate objects(LocalDatesRepositoryTests.kt:29)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
`

I have no clue, what is wrong with my LocalDateSerializer.

Can you help me please?