-
Type:
Bug
-
Resolution: Won't Fix
-
Priority:
Minor - P4
-
None
-
Affects Version/s: 5.5.0
-
Component/s: SDAM
-
None
-
Java Drivers
-
None
-
None
-
None
-
None
-
None
-
None
When connecting to a 3.4 or older server, the driver throws a MongoTimeoutException from server selection:
Exception in thread "main" com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[ {address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketReadException: Prematurely reached end of stream}}]
The excpected result is:
Exception in thread "main" com.mongodb.MongoIncompatibleDriverException: Server at localhost:27017 reports wire version 5, but this version of the driver requires at least 8 (MongoDB 4.2).
The regression is caused by a change made in scope of JAVA-5831, where the method body of CommandMessage#isServerVersionKnown was changed from
return settings.getMaxWireVersion() >= FOUR_DOT_ZERO_WIRE_VERSION;
to
return settings.getMaxWireVersion() != UNKNOWN_WIRE_VERSION;
This method is used by CommandMessage to determine whether OP_MSG or OP_QUERY is used. If it returns true, OP_MSG is used, otherwise OP_QUERY is used.
We didn't expect that change to make a difference, but there is some code in InternalStreamConnectionInitializer#completeConnectionDescriptionInitialization that triggers this bug. The sequence of events is:
- DefaultServerMonitor opens a new connection.
- isMaster command is sent. Because maxWireVersion is not yet known, OP_QUERY is used
- description.getConnectionDescription().getConnectionId().getServerValue()} is {{null}} because the connectionId field was only added to the handshake reply starting with the 4.2 server release. So the initializer sends a getlasterror command to the server, which (for reasons lost to history) is included in that command's reply. But because maxWireVersion is now known, OP_MSG is used to send the getlasterror command.
- Since the 3.4 server doesn't recognized OP_MSG, it has no way to respond, and so it just closes the connection and a MongoSocketReadException is thrown.
- That causes the server selection loop to continue until the server selection timeout is reached, after which a MongoTimeoutException is thrown with the message shown above.
There are two potential fixes for this:
- The first is to revert the change to CommandMessage#isServerVersionKnown
- The second is to remove the code that sends a getlasterror command when the connection id not send in the handshake reply. We should do this anyway eventually, since now that 4.2 is the minimum server version that the driver supports we should never actually execute that code unless the server version is unsupported, in which case it has no value anyway.
One path forward is to do the first one in a patch release and the second in a minor release. Or we can just do the second one, and then the first one is not needed.
- is caused by
-
JAVA-5831 Mark Server version 4.0 as EOL from driver's PoV (Min server version as 4.2, minWireVersion as 8)
-
- Closed
-
- related to
-
DRIVERS-2944 Update handshake spec to allow using OP_MSG exclusively
-
- Backlog
-