ZagTrader

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

QuickFIX/J event log of the side that logs out
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 parser

Where 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:

EngineSequence numbersOther 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
  • .body and .header hold the messages you sent, so you can answer a ResendRequest. Deleting them means resends become gap fills.
  • .session holds 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

  1. 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).
  2. 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.
  3. Change the number while the session is logged out, then let it log on.
QuickFIX/J
Session session = Session.lookupSession(sessionID);
session.setNextSenderMsgSeqNum(2041);  // the next number you will send
session.setNextTargetMsgSeqNum(874);   // the next number you expect
QuickFIX/n
Session session = Session.LookupSession(sessionID);
session.NextSenderMsgSeqNum = 2041;
session.NextTargetMsgSeqNum = 874;
QuickFIX C++
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=Y resets 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=Y so 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

  1. QuickFIX/J source: Session.java (setting names, defaults, logout and reject texts)
  2. QuickFIX/J source: FileStore.java (store files)
  3. QuickFIX/J source: AcceptorIoHandler.java (unknown session at logon)
  4. QuickFIX/J user manual: Configuration
  5. QuickFIX/n source: Session.cs (reject handling, sequence texts)
  6. QuickFIX/n source: FileStore.cs (store files)
  7. QuickFIX/n documentation: Configuration
  8. QuickFIX C++ source: Session.cpp (reject handling, sequence texts)
  9. QuickFIX C++ source: FileStore.cpp (store files)
  10. 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