Reconnecting the FIX adapter after MsgSeqNum too low error

Reconnecting the FIX adapter after MsgSeqNum too low error

book

Article ID: KB0076047

calendar_today

Updated On:

Products Versions
TIBCO Streaming -

Description

The FIX adapter failed to connect to the counter-party and in the logs I see it is reporting a "MsgSeqNum too low" error in response to the Logon(A) request.

Issue/Introduction

Explanation of the error and strategies to recover

Resolution

The FIX protocol uses a message sequence number, "MsgSeqNum", to identify when a message has been missed. During a FIX session, both the client (Sender) and the server (Target) build a ledger of all messages sent and received. A FIX "session" may continue with a continuous ledger across several Logout(5) and Logon(A) events.

In the TIBCO Streaming FIX adapter, using the QuickFIX/J engine, the ledger by default is the "{session}.messages.log" in the "store/" subdirectory. Using the StreamBase High-Performance FIX engine (EPAM B2BITS FIX Antenna) the store location is the "fixajLogs/" subdirectory.

If the session store is damaged before the next Logon(A) FIX message, the FIX Acceptor (the Target's FIX engine) will be expecting the Logon(A) message to have a MsgSeqNum higher than the last seen MsgSeqNum from the Initiator (the Sender's FIX client) and the client will typically be starting over with a MsgSeqNum equal to one (1), which is too low. If the Target permitted the Logon(A) with sequence numbers it had already seen before in the session, then it would have to corrupt its own ledger and replace the old messages as MsgSeqNum values are re-used. This is not allowed since the ledger must be maintained for replay and recovery, and is often preserved for legal reasons since it is the exact historical record of financial transactions.

Ways to recover:
  
A. If the counter-party supports resetting the session, then both the Initiator and Acceptor may start at zero again in a new session and this error can be avoided. The Initiator (FIX client) must add to the Logon(A) message the ResetSeqNumFlag(141)='Y' (for Yes). This may be configured for automatic insertion by using the "ResetOnLogon=Y" (QuickFIX/J engine configuration file) or "<reset-on-logon>true</reset-on-logon>" (StreamBaseFIX configuration file).

B. The Logon(A) Reject(5) message usually identifies the expected MsgSeqNum, like this:
"MsgSeqNum too low, expecting 17 but received 1"
The expected value is not easily accessible to the EventFlow application, but in response you may get this value from the log and then use the FIX Input Adapter, Command input port, to send a command tuple to change the next MsgSeqNum to higher than expected using adapter command "SetSenderMsgSeqNum". For example, set tuple fields:
  Command, "SetSenderMsgSeqNum"
  BeginSeqNo: 20

(The value '20' is higher than the expected '17' from the example Reject message.)
After the "SetSenderMsgSeqNum" command, submit a new "Logon" command, which should avoid this error and succeed.

This results in message sequence:
1. 8=FIX.4.2,9=107,35=5,34=25,49=VENUE1,52=20200117-18:11:49.760,56=CLIENT1,58=MsgSeqNum too low, expecting 17 but received 8,10=183,
2. 8=FIX.4.2,9=56,35=5,34=9,49=CLIENT1,52=20200117-18:11:49.765,56=VENUE1,10=141,
3. 8=FIX.4.2,9=69,35=A,34=20,49=CLIENT1,52=20200117-18:12:59.758,56=VENUE1,98=0,108=30,10=227,
4. 8=FIX.4.2,9=69,35=A,34=26,49=VENUE1,52=20200117-18:12:59.759,56=CLIENT1,98=0,108=30,10=234,

which shows that the client MsgSeqNum went from '8' to '20' and resulted in a successful logon.

You may also use this approach with an arbitrarily high new MsgSeqNum value (for example, 50000). When connected both the client and counter-party FIX engines will send ResendRequest(2) messages and the client engine will reply with a SequenceReset(4) administration message telling the counter-party to skip over the missing MsgSeqNum values.

To facilitate this type of recovery you may use the FIX input adapter command "GetMsgSeqNums" at intervals and store these to a location on your file-system where they may be easily retrieved later. This will allow you to have a good guess for the highest MsgSeqNum sent. You may then use that guess when re-connecting using the "SetSenderMsgSeqNum" command.