How Exception Code 02 Appears on the Wire
In standard Modbus protocol execution, when a master or client issues a valid query, the slave executes the operation and returns the requested register contents. However, if the query points to an address outside the slave's allowed register map, the slave generates an Exception Response Frame:
- Slave ID: Echoes the targeted device address (e.g.,
0x01). - Exception Function Code: The master's original Function Code with its most significant bit (bit 7,
0x80) set to 1. For example, a Read Holding Registers request (0x03) becomes0x83; a Read Input Registers request (0x04) becomes0x84; a Write Multiple Registers request (0x10) becomes0x90. - Exception Code Byte: The literal byte value
0x02, indicating Illegal Data Address. - Error Checking: 16-bit CRC checksum (Modbus RTU) or MBAP length header (Modbus TCP).
[01] [03] [00] [63] [00] [01] [75] [D5]
// Modbus RTU Slave Exception Response (Exception Code 02):
[01] [83] [02] [C0] [F1]
// 0x01 = Slave ID | 0x83 = Error FC (0x03 + 0x80) | 0x02 = ILLEGAL DATA ADDRESS | 0xC0F1 = CRC-16
The Top 5 Causes of Modbus Exception Code 02
1. The 0-Based vs 1-Based Offset Off-by-One Error
The most common source of Exception 02 stems from confusing Protocol Data Unit (PDU) wire addressing with PLC application memory mapping:
- PDU Wire Address (0-Based): The actual bits transmitted over the serial cable or Ethernet packet range from
0x0000to0xFFFF(0 to 65,535). - PLC / Documentation Address (1-Based): Human documentation and classic Modicon notation starts counting at register 1. In this scheme, Holding Register 1 is denoted as
40001(or400001in extended 6-digit notation).
To poll register 40001, the standard requires subtracting 1, transmitting PDU address 0x0000 over the wire. However, if your SCADA software (e.g., Ignition, Wonderware, Node-RED, or Python pymodbus) is configured for 0-based indexing and you enter 1, the master transmits PDU address 0x0001 (register 40002).
If a field sensor only contains a single register at address 40001 (PDU 0x0000), transmitting PDU 0x0001 causes the device to query non-existent memory and reply with Exception 02.
2. Block Read Quantity Overflow Exceeding Memory Boundaries
Control engineers often poll registers in contiguous blocks to optimize network throughput. For example, instead of issuing ten separate 1-register requests, a master issues a single Function Code 03 read with a Quantity of 10 registers.
The Modbus specification dictates that a slave device must validate the entire requested address span:
End Address = Starting Address + Quantity - 1
Suppose an energy meter's register map contains registers from 40001 to 40020. If your master requests 10 registers starting at address 40015, the query attempts to read registers 40015 through 40024. Because registers 40021 through 40024 do not exist, the device will not return partial data—it will abort the entire transaction and return Exception Code 02.
3. Modbus Table and Function Code Mismatches
The Modbus protocol defines four distinct object types, each accessed with specific function codes:
| Object Type | Memory Prefix | Access Type | Valid Function Codes |
|---|---|---|---|
| Discrete Output (Coil) | 0xxxx (00001–09999) | Read / Write | FC 01, FC 05, FC 15 |
| Discrete Input | 1xxxx (10001–19999) | Read Only | FC 02 |
| Input Register | 3xxxx (30001–39999) | Read Only | FC 04 |
| Holding Register | 4xxxx (40001–49999) | Read / Write | FC 03, FC 06, FC 16 |
Many microcontrollers, RTUs, and smart sensors store process measurements exclusively in Input Registers (FC 04). If a SCADA engineer attempts to read these addresses using Read Holding Registers (FC 03), the slave inspects its Holding Register table, finds no data at that address, and returns Exception Code 02.
4. Gaps in Sparse Register Maps
In complex industrial equipment (such as Variable Frequency Drives or Solar Inverters), manufacturer register maps are often sparse. For example, a drive may map status words at 40001–40005, motor speed at 40010, and fault codes at 40050, leaving addresses 40006–40009 unassigned.
If your polling driver attempts to optimize communication by requesting a contiguous block from 40001 with a quantity of 15 (spanning the gap 40006–40009), devices with strict validation will reject the entire request with Exception 02 upon encountering the first unassigned address in the range.
5. 32-Bit Float32 and Int32 Register Boundary Violations
Because standard Modbus registers are 16 bits wide, 32-bit floating-point numbers (IEEE 754) and 32-bit signed/unsigned integers require two contiguous registers (e.g., 40001 and 40002).
Certain embedded devices and flow computers (such as Daniel or Enron Modbus implementations) treat 32-bit registers as atomic variables. If you attempt to poll only 1 register (16 bits) from a variable mapped strictly as a 32-bit value, or if you point your starting address at the second word of a pair (e.g., 40002 instead of 40001), the slave firmware rejects the misaligned read with Exception 02.
Step-by-Step Diagnostic Workflow to Fix Exception 02
-
Test Single-Register Reads (Quantity = 1): Never start troubleshooting with block reads. Change your master request quantity to
1. If polling individual registers succeeds, your issue is block length overflow or a sparse gap in the device register map. -
Verify 0-Based vs 1-Based Addressing: Check your device manual. If a register is listed as
40001, try polling PDU address0, then try PDU address1. Many master drivers include an explicit configuration checkbox: "Zero-based addressing" or "Subtract 1 from register address". - Switch Function Codes (FC 03 vs FC 04): If reading holding registers (FC 03) fails with Exception 02, verify whether the documentation specifies Input Registers. Switch your polling function code to FC 04.
-
Inspect Hexadecimal Packet Logs: Use a packet monitor to inspect the exact transmitted hex bytes. Verify that the two-byte starting address matches the expected hex representation (e.g. register 40100 1-based = 99 decimal =
0x0063).
Simulate and Isolate Register Mappings with ModbusSimulator
When troubleshooting Exception 02 on a live production line, stopping PLCs or rewiring live RS-485 networks risks plant downtime. The fastest, safest way to resolve register mapping mismatches is using ModbusSimulator on your engineering workstation.
With ModbusSimulator, you can:
- Simulate Exact Slave Register Maps: Create holding, input, discrete, and coil tables with custom boundary limits and test how your master handles edge cases.
- Inspect Real-Time Traffic Frames: View decoded incoming frames and raw hex bytes in the integrated traffic monitor to instantly identify off-by-one PDU address discrepancies.
- Verify 32-Bit Float & Integer Formats: Test Big-Endian, Little-Endian, Word-Swapped, and Byte-Swapped 32-bit values without guessing memory layout.
- Simulate Multiple Slave IDs (1–247): Emulate complex multi-device networks over Modbus TCP or Modbus RTU virtual COM ports.
Eliminate Modbus Address Guesswork
Test Modbus RTU and Modbus TCP applications with high-resolution visual register grids, dynamic waveform generation, and zero hardware requirements.
Download ModbusSimulator Free →Frequently Asked Questions (FAQs)
1. What does Modbus Exception Code 02 (Illegal Data Address) mean?
Modbus Exception Code 02 indicates that the register address received by the slave does not exist in its internal memory map, or the requested block of registers extends beyond the valid memory range.
2. Why does my master get Exception 02 when reading register 40001?
In the physical Modbus protocol, wire addresses start at 0. If your master transmits 1 instead of 0 over the wire, it asks for register 40002. If the slave only has 1 register mapped, it returns Exception Code 02. Subtract 1 from your register address or toggle the 0-based offset option in your driver.
3. How does block reading trigger Exception 02?
Slaves validate the entire requested block (Starting Address + Quantity - 1). If you request 10 registers starting at 40015, but the slave's register map ends at 40020, the request exceeds memory boundaries and the slave aborts with Exception 02.
4. Can an incorrect Function Code cause Exception 02?
Yes. If a device stores data in Input Registers (FC 04) and you attempt to read with Read Holding Registers (FC 03), the slave looks in its holding register table, finds no entry, and returns Exception Code 02.
5. What is the difference between Exception 01 and Exception 02?
Exception Code 01 (Illegal Function) means the slave does not support the function code itself (e.g. requesting FC 16 write on a read-only device). Exception Code 02 (Illegal Data Address) means the function code is supported, but the targeted memory address or register range is invalid.
6. How can I verify my register polling before field deployment?
Use ModbusSimulator to emulate your slave device with custom register tables, inspect exact PDU hex bytes in the traffic monitor, and confirm that both single-register and block queries succeed with zero exception responses.