-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Kotlin
-
None
-
Java Drivers
-
None
-
None
-
None
-
None
-
None
-
None
Summary
When updating a kotlinx.datetime.Instant field with the non-default InstantAsBsonDateTime serializer using MongoCollection.updateOne, the serializer is seemingly not applied and the instant gets serialized as a string. This leads to
BsonInvalidOperationException on any subsequent find operations as deserialization fails.
Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).
This happens with the latest driver and kotlinx versions
org.mongodb:mongodb-driver-kotlin-coroutine:5.3.1 org.mongodb:mongodb-driver-kotlin-extensions:5.3.1 org.mongodb:bson-kotlinx:5.3.1 org.jetbrains.kotlinx:kotlinx-serialization-core:1.8.0 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1
How to Reproduce
The behaviour is reproducible with the following test
import com.mongodb.ConnectionString import com.mongodb.MongoClientSettings import com.mongodb.kotlin.client.coroutine.MongoClient import com.mongodb.kotlin.client.model.Filters.eq import com.mongodb.kotlin.client.model.Updates.set import io.kotest.assertions.throwables.shouldNotThrow import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.nulls.shouldNotBeNull import kotlinx.coroutines.flow.firstOrNull import kotlinx.datetime.Clock import kotlinx.datetime.Instant import kotlinx.serialization.Contextual import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.bson.BsonInvalidOperationException import org.bson.types.ObjectId import org.testcontainers.containers.MongoDBContainer import org.testcontainers.utility.DockerImageName class MongoTest : FunSpec({ @Serializable data class Foo( @SerialName("_id") @Contextual val id: ObjectId = ObjectId(), @Contextual // Or @Serializable(with = InstantAsBsonDateTime::class) val instant: Instant, ) val mongoDbContainer = MongoDBContainer(DockerImageName.parse("mongo:8.0")).also { it.start() } val client = MongoClient.create( MongoClientSettings.builder() .applyConnectionString(ConnectionString(mongoDbContainer.connectionString)) .build() ) val database = client.getDatabase("foo") val collection = database.getCollection<Foo>("foos") test("should serialize and deserialize Foo correctly after updating instant") { val foo = Foo(instant = Clock.System.now()) collection.insertOne(foo) // updating instant field with replaceOne works as expected val newInstant = Clock.System.now() collection.replaceOne(Foo::id eq foo.id, foo.copy(instant = newInstant)) var found = collection.find(Foo::id eq foo.id).firstOrNull() found.shouldNotBeNull() // deserializing instant field after updating it with updateOne throws BsonInvalidOperationException // Caused by: org.bson.BsonInvalidOperationException: Value expected to be of type DATE_TIME is of unexpected type STRING val anotherNewInstant = Clock.System.now() collection.updateOne(Foo::id eq foo.id, Foo::instant set anotherNewInstant) shouldNotThrow<BsonInvalidOperationException> { collection.find(Foo::id eq foo.id).firstOrNull() } } })
Steps to reproduce. If possible, please include a Short, Self Contained, Correct (Compilable), Example.
Additional Background
Please provide any additional background information that may be helpful in diagnosing the bug.