[JAVA-3622] Unable to serialize document with list of documents that contain an "_id" field Created: 10/Feb/20  Updated: 28/Oct/23  Resolved: 27/Feb/20

Status: Closed
Project: Java Driver
Component/s: BSON
Affects Version/s: 4.0.0
Fix Version/s: 4.0.0

Type: Bug Priority: Major - P3
Reporter: Ross Lodge Assignee: John Stewart (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Driver 4.0.0-beta1. OpenJDK 11. Mongo server 4.2.1 on osX.



 Description   

Using a simple, vanilla insert like the below, the driver reports:

An EndArray value cannot be written to the root level of a BSON document

Simple reproduction scenario:

final MongoClient mongoClient = MongoClients.create(
    MongoClientSettings.builder()
        .applyConnectionString(new ConnectionString("mongodb://localhost:27017"))
        .uuidRepresentation(UuidRepresentation.STANDARD)
        .build()
);
 
mongoClient.getDatabase("unittest")
    .getCollection("listError")
    .insertOne(
        new Document()
            .append("_id", new org.bson.types.ObjectId())
            .append(
                "items",
                Collections.singletonList(
                    new Document()
                        .append("_id", new org.bson.types.ObjectId())
                )
            )
    );

The stack trace is: 

org.bson.BsonInvalidOperationException: An EndArray value cannot be written to the root level of a BSON document.	at org.bson.AbstractBsonWriter.throwInvalidState(AbstractBsonWriter.java:740)
	at org.bson.AbstractBsonWriter.checkPreconditions(AbstractBsonWriter.java:701)
	at org.bson.AbstractBsonWriter.writeEndArray(AbstractBsonWriter.java:341)
	at com.mongodb.internal.connection.BsonWriterDecorator.writeEndArray(BsonWriterDecorator.java:68)
	at com.mongodb.internal.connection.LevelCountingBsonWriter.writeEndArray(LevelCountingBsonWriter.java:66)
	at com.mongodb.internal.connection.IdHoldingBsonWriter.writeEndArray(IdHoldingBsonWriter.java:133)
	at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:222)
	at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:193)
	at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:212)
	at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:154)
	at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
	at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
	at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
	at com.mongodb.internal.connection.SplittablePayload$WriteRequestEncoder.encode(SplittablePayload.java:200)
	at com.mongodb.internal.connection.SplittablePayload$WriteRequestEncoder.encode(SplittablePayload.java:187)
	at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
	at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
	at com.mongodb.internal.connection.BsonWriterHelper.writeDocument(BsonWriterHelper.java:77)
	at com.mongodb.internal.connection.BsonWriterHelper.writePayload(BsonWriterHelper.java:59)
	at com.mongodb.internal.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:145)
	at com.mongodb.internal.connection.RequestMessage.encode(RequestMessage.java:138)
	at com.mongodb.internal.connection.CommandMessage.encode(CommandMessage.java:59)
	at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:247)
	at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:99)
	at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:500)
	at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:71)
	at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:224)
	at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:202)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:118)
	at com.mongodb.internal.operation.MixedBulkWriteOperation.executeCommand(MixedBulkWriteOperation.java:419)
	at com.mongodb.internal.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:245)
	at com.mongodb.internal.operation.MixedBulkWriteOperation.access$700(MixedBulkWriteOperation.java:71)
	at com.mongodb.internal.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:189)
	at com.mongodb.internal.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:180)
	at com.mongodb.internal.operation.OperationHelper.withReleasableConnection(OperationHelper.java:500)
	at com.mongodb.internal.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:180)
	at com.mongodb.internal.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:71)
	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:207)
	at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:1008)
	at com.mongodb.client.internal.MongoCollectionImpl.executeInsertOne(MongoCollectionImpl.java:469)
	at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:452)
	at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:446)

It appears to be because IdHoldingBsonWriter, when it writes its internal EndArray token, finds the wrong state: 

@Override
public void writeEndArray() {
    super.writeEndArray();
 
    if (isWritingId()) {
        getIdBsonWriter().writeEndArray();
        if (getIdBsonWriter().getCurrentLevel() == 0) {
            getIdBsonWriter().writeEndDocument();
            id = new RawBsonDocument(getBytes()).get(ID_FIELD_NAME);
        }
    }
}



 Comments   
Comment by Githook User [ 27/Feb/20 ]

Author:

{'name': 'John Stewart', 'username': 'jstewart-mongo', 'email': 'john.stewart@mongodb.com'}

Message: Decrement the level of BsonWriter after checking _id in
IdHoldingBsonWriter.writeEndArray

JAVA-3622
Branch: 4.0.x
https://github.com/mongodb/mongo-java-driver/commit/07f0f3e85ade9d4a00552e789dd35d27b495a716

Comment by Githook User [ 27/Feb/20 ]

Author:

{'name': 'John Stewart', 'username': 'jstewart-mongo', 'email': 'john.stewart@mongodb.com'}

Message: Decrement the level of BsonWriter after checking _id in
IdHoldingBsonWriter.writeEndArray

JAVA-3622
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/e619c4f1e0b2c51fcbdae8b7270332e96e4a904a

Comment by Jeffrey Yemin [ 27/Feb/20 ]

john.stewart please backport to the 4.0.x and 3.12.x branches.

Generated at Thu Feb 08 09:00:02 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.