QuickFIX "MsgSeqNum too low": Reset Sequence Numbers Safely and Fix the File Store
Written and maintained by ZagTrader. Last reviewed . How this page is sourced and checked
QuickFIX logs out with "MsgSeqNum too low, expecting X but received Y" when a message arrives with a lower number than expected and without PossDupFlag. The protocol side is on the MsgSeqNum too low page. This guide covers the QuickFIX side: where the numbers live, how to change them without losing messages, and why a store goes stale.
How it looks
20261020-07:00:00.000: Accepting session FIX.4.4:SELLSIDE->BUYSIDE from /10.0.0.5:51544 20261020-07:00:00.002: MsgSeqNum too low, expecting 2041 but received 1 20261020-07:00:00.004: 8=FIX.4.4|9=112|35=5|49=SELLSIDE|56=BUYSIDE|34=873|52=20261020-07:00:00.004|58=MsgSeqNum too low, expecting 2041 but received 1|10=244|
The same text appears in the Logout (Text (58)) that the counterparty receives. SOH (0x01) is shown as |.
Open this log in the parserWhere QuickFIX keeps the numbers
With the file store, each session has a set of files in FileStorePath named after the session ID, for example FIX.4.4-BUYSIDE-SELLSIDE:
| Engine | Sequence numbers | Other files |
|---|---|---|
| QuickFIX/J | .senderseqnums and .targetseqnums, binary (written with Java's writeUTF) | .body, .header, .session |
| QuickFIX/n | .seqnums: sender : target as text | .body, .header, .session |
| QuickFIX C++ | .seqnums: sender : target as text | .body, .header, .session |
.bodyand.headerhold the messages you sent, so you can answer a ResendRequest. Deleting them means resends become gap fills..sessionholds the creation time of the session period. At start-up QuickFIX compares it with the schedule and resets everything if it belongs to an earlier period (QuickFIX/J logs "Session state is not current; resetting").- Do not edit QuickFIX/J's sequence files in a text editor: the two bytes in front of the digits are a length, and a hand-edited file breaks the store. Use the API below.
Set the numbers safely
- Compare both sides' logs first. Decide which side has the wrong number; the text gives you X (what the receiver expects) and Y (what arrived).
- If your outgoing number is too low, raise it to X. Do not lower the counterparty's expected number to accept Y unless you know messages Y to X-1 are new to them.
- Change the number while the session is logged out, then let it log on.
Session session = Session.lookupSession(sessionID);
session.setNextSenderMsgSeqNum(2041); // the next number you will send
session.setNextTargetMsgSeqNum(874); // the next number you expectSession session = Session.LookupSession(sessionID);
session.NextSenderMsgSeqNum = 2041;
session.NextTargetMsgSeqNum = 874;FIX::Session* session = FIX::Session::lookupSession(sessionID);
session->setNextSenderMsgSeqNum(2041);
session->setNextTargetMsgSeqNum(874);For a full restart at 1 on both sides, agree it with the counterparty and use a Logon with 141=Y: in QuickFIX, ResetOnLogon=Y for that logon, or session.reset() in QuickFIX/J and QuickFIX C++, which logs out and resets. Anything not yet delivered in either direction is lost, so reconcile open orders afterwards.
ResetOnLogon, ResetOnLogout, ResetOnDisconnect
- Use them only when the counterparty works the same way. One side resetting at each logon while the other keeps its numbers produces this error after every reconnect.
ResetOnDisconnect=Yresets on every dropped connection, so a network blip during the day throws away anything in flight.- With an initiator, any of the three settings makes QuickFIX send 141=Y on a Logon when both numbers are at 1.
- Most daily sessions need none of them: the schedule resets the numbers at StartTime. See session schedules.
Stale and locked stores
- Restored from a backup, copied from another server, or rolled back with a container image: the store is behind and your first message is too low for the counterparty. Keep FileStorePath on persistent storage outside the image.
- Two processes on the same store (a second instance, a forgotten test run, a failover node started too early) interleave numbers and corrupt the files. QuickFIX/J and QuickFIX C++ do not lock the store files; the first sign is often this error. QuickFIX/J refuses a second connection for a session that is already logged on with "Multiple logons/connections for this session are not allowed".
- On Windows, QuickFIX/n opens its store files for exclusive writing, so a second process fails at start with a file-in-use error. Stop the other process instead of deleting the files.
- A standby engine that shares the store needs
RefreshOnLogon=Yso it reads the latest numbers when it takes over.
Questions
- How do I reset sequence numbers in QuickFIX/J?
- With the session logged out, call setNextSenderMsgSeqNum and setNextTargetMsgSeqNum on the Session, or session.reset() to log out and reset both to 1. Agree a reset to 1 with the counterparty first.
- Can I delete the QuickFIX store files to reset?
- With the engine stopped, deleting a session's store files resets both numbers to 1 and removes the messages you would need for resends. Only do it when the counterparty resets too.
- Why does QuickFIX reset my numbers when it starts?
- The store's creation time belongs to an earlier schedule period, so QuickFIX starts a new period. Check StartTime, EndTime and the day settings.
The FIX side of the problem
What the error means on any FIX engine, with example messages you can open in the parser:
Reference
Sources
- QuickFIX/J source: Session.java (setting names, defaults, logout and reject texts)
- QuickFIX/J source: FileStore.java (store files)
- QuickFIX/J source: AcceptorIoHandler.java (unknown session at logon)
- QuickFIX/J user manual: Configuration
- QuickFIX/n source: Session.cs (reject handling, sequence texts)
- QuickFIX/n source: FileStore.cs (store files)
- QuickFIX/n documentation: Configuration
- QuickFIX C++ source: Session.cpp (reject handling, sequence texts)
- QuickFIX C++ source: FileStore.cpp (store files)
- QuickFIX C++ documentation: Configuration
Setting names, defaults and message texts were checked against the projects' source code and documentation on the review date shown at the top of the page. Behaviour can change between releases; check the version you run. This guide is independent and not affiliated with the QuickFIX projects.
See also
More QuickFIX guides
- QuickFIX/J vs QuickFIX/n vs QuickFIX C++: Which One to Use
- QuickFIX Session Settings Explained: Configuration Reference
- QuickFIX with FIX 5.0 SP2: FIXT.1.1, Transport and Application Dictionaries
- Custom Fields and a Custom Data Dictionary in QuickFIX
- Repeating Groups in QuickFIX: Reading, Writing and Validation Errors
- QuickFIX Session Schedules: Daily vs Weekly Sessions, Time Zones and Sunday to Thursday Markets
- QuickFIX "Tag not defined for this message type": Causes and Fixes
- QuickFIX "Conditionally Required Field Missing": Why Your Handler Caused It
- QuickFIX "Incorrect data format for value": Field Types and Fixes
- QuickFIX Logon Problems: Session Not Found, CompID Mismatch and Rejected Logons
- QuickFIX SSL and TLS: Setup per Engine and Handshake Failures
- QuickFIX onMessage Not Called: Message Cracking Problems
- Reading and Analyzing QuickFIX Logs: messages.log and event.log