ZagTrader

Garbled messages

CheckSum mismatch: invalid checksum (tag 10)

The three-digit value in CheckSum (10) does not match the sum of the message bytes modulo 256. The receiver treats the message as garbled and ignores it; the next message then shows up as a sequence gap.

What it means

CheckSum is the sum of every byte from the start of 8= up to and including the SOH before 10=, modulo 256, written as exactly three digits. A sum of 7 is sent as 007.

It is a transmission check, not a security feature. A mismatch almost always means the sender computed it over different bytes from the ones it sent.

Like a bad BodyLength, a bad CheckSum gets no Reject. The message is dropped and its sequence number is not consumed.

Common causes

  • No zero padding: 10=92 instead of 10=092.
  • Computed over a copy of the message that uses | or ^ instead of SOH.
  • A field changed after the checksum was computed, often by a gateway, or by a replay that added PossDupFlag.
  • Summing characters instead of bytes for non-ASCII text.
  • Including the 10= field itself, or leaving out the last SOH before it.

How to fix it

On the side that sent the message

  • Compute CheckSum last, over the exact bytes you write to the socket, and pad it to three digits.
  • If something between your engine and the counterparty rewrites fields, it must recompute BodyLength and CheckSum.
  • Paste the message into the parser to see the expected value.

On the side that raised the error

  • Log the raw bytes of dropped messages and send them to the counterparty with the expected value.
  • Check that your own logging does not alter the bytes you compare. Some loggers replace SOH, which makes a correct message look wrong when it is checked from the log.

Example

A Heartbeat with a wrong CheckSum, then the same message with the correct value.

  1. 1. Wrong CheckSum

    8=FIX.4.4|9=61|35=0|49=SELLSIDE|56=BUYSIDE|34=2210|52=20261020-12:00:30.000|10=197|
  2. 2. Correct CheckSum

    8=FIX.4.4|9=61|35=0|49=SELLSIDE|56=BUYSIDE|34=2210|52=20261020-12:00:30.000|10=180|

SOH (0x01) is shown as |. BodyLength (9) and CheckSum (10) are calculated as if every | were SOH, except where the example is about a wrong value.

Open this example in the parser

Questions

How is the FIX checksum calculated?
Add up the value of every byte from the 8 of 8= to the SOH just before 10=, take the total modulo 256 and write it as three digits with leading zeros.
Do I compute the checksum with | or with SOH?
With SOH (0x01). The | in logs is only for display. The parser computes the value as if every delimiter were SOH, whatever delimiter the log uses.

Reference

Related errors

All FIX errors · FIX guides