— Understanding & Handling Errors
(Module 4 · Modbus Data Model & Function Codes)
Learning objectives
By the end of this chapter you will be able to …
- Describe the exact PDU structure of a Modbus exception frame (serial & TCP).
- Identify every public exception code (01 – 0B) and map it to its most likely field root-causes.
- Design client-side logic that backs off, retries, or escalates correctly—without flooding the bus.
- Instrument servers so they emit meaningful exceptions instead of silent time-outs.
- Diagnose hard-to-find issues (off-by-one, illegal value, device busy) with a repeatable, five-step workflow.
13.1 What is an exception response?
A Modbus server that cannot honour a request must answer anyway—it flips the MSB of the Function Code and appends a one-byte Exception Code.
An exception frame is therefore a deterministic, bandwidth-cheap error report—not a timeout.
Normal response | Exception response |
---|---|
FC = 0x03 | FC = 0x83 (0x80 + original FC) |
Data bytes | 1 byte Exception Code |
(Timing on wire identical; size only 5 B RTU / 9 B TCP.)
13.2 Byte-level anatomy
13.2.1 RTU (serial)
Addr | FC+0x80 | ExCode | CRClo | CRChi
13.2.2 TCP (MBAP)
Transaction-ID | Protocol-ID | Length=0x0003 | Unit-ID | FC+0x80 | ExCode
Inspection trick
tcp.len == 3
ANDmodbus.function_code >= 0x80
→ Wireshark filter for exceptions only.
13.3 Exception code reference
Code | Hex | Description | Most common real-world triggers | Server-side fix | Client-side action |
---|---|---|---|---|---|
01 | 0x01 | Illegal Function | Master polls FC 06 but slave is RO sensor | Implement FC or document unsupported | Drop from poll list; log once |
02 | 0x02 | Illegal Data Address | Offset beyond register map; wrong 0-/1-base | Expand map; correct datasheet | Correct address; retry immediately |
03 | 0x03 | Illegal Data Value | Qty = 0 or > spec; write value out-of-range | Validate arguments better | Clamp or display clear error |
04 | 0x04 | Slave Device Failure | Sensor open-circuit; arithmetic fault | Watchdog/reboot; raise alarm | Slow retry with exponential back-off |
05 | 0x05 | Acknowledge | Long internal movement; write accepted but not done | Return when done instead | Poll same address until clear |
06 | 0x06 | Slave Device Busy | Flashing firmware; HMI config mode | Queue or reject new jobs | Retry after 1–5 s, stop after N=3 |
08 | 0x08 | Memory Parity Error | EEPROM CRC fail | Spare memory bank / reset | Stop polling; manual intervention |
0A | 0x0A | Gateway Path Unavailable | RTU loop offline | Auto-heal RS-485, raise SNMP trap | Reroute or wait for path recovery |
0B | 0x0B | Gateway Target Device Failed to Respond | Slave power-off or address clash | Isolate glitching node | Skip node; alert maintenance |
(Figure 13-1 placeholder: colourful cheat-sheet wheel of exception codes.)
13.4 Timeouts vs exceptions vs silent discard
Phenomenon | Wire evidence | Likely layer | Resolution |
---|---|---|---|
Exception | 5 / 9 B reply | Application | Fix request parameters |
Timeout | No reply within “Response Timeout” | Physical / link | Check wiring, baud, address |
Silent discard | Reply CRC bad (scope shows), master drops | CRC calc bug or noise | Inspect bias, termination, CRC routine |
Rule Always aim for exception > timeout. A device that never times out is infinitely easier to debug.
13.5 Best-practice client logic
on_response(frame):
if frame.is_exception():
code = frame.ex_code
if code in {ACKNOWLEDGE, DEVICE_BUSY}:
sleep(short_retry)
retry_same_request()
elif code in {ILLEGAL_FUNC, ILLEGAL_ADDR}:
disable_poll(entry)
alert_config_team()
else: # 04, 08, 0B …
retry_count += 1
if retry_count >= Nmax:
raise_alarm(slave_id, code)
else:
retry_count = 0
process_data(frame)
Short_retry = 250 ms for busy/ack; Nmax = 3 configurable.
13.6 Server-side guidelines
Topic | Recommendation |
---|---|
Granular checks | Return Illegal Data Value for out-of-range instead of generic Device Failure. |
*Watchdog | If ISR > 100 ms, reply Acknowledge then complete. |
Logging | Mirror exception frames to Syslog (ex=02 addr=0x1234 qty=10 ). |
Testing | Fuzz tool: sweep FC + offsets outside map; confirm correct ex-code each case. |
(Listing 1: C pseudo showing exception builder in slave firmware.)
13.7 RTU-to-TCP gateway subtleties
13.7.1 Timeout conversion
If RTU slave times out → gateway should forward 0B Gateway Target Failed to Respond to TCP master instead of letting TCP session stall.
13.7.2 Path unavailable
If RS-485 bus offline → gateway returns 0A to all Unit-IDs on that bus.
(Figure 13-2 placeholder: flow diagram of gateway translating serial timeout → exception.)
13.8 Testing & diagnostics workflow
- Capture traffic (
serial-tap
or Wireshark). - Filter exceptions (
modbus.exception_code
). - Correlate with SCADA error log timestamp.
- Cross-check slave diagnostics (LED, HMI status).
- Iterate: adjust timing, address, range; re-capture.
Lab 13-1: Download the sample
.pcapng
file and identify why Slave 17 returns code 02 at 12:47:05.
13.9 Exception-aware polling strategies
Strategy | Bandwidth | Robustness | Use-case |
---|---|---|---|
Fast retry, skip on 3× | Med | Good | Small loop < 10 slaves |
Exponential back-off | Low | Excellent | Unreliable radio links |
Buddy system (pair read + health coil) | High | Excellent | Safety-critical / pumps |
Adaptive (increase interval on repeated 05/06) | Med–low | Good | Drives in auto-tune |
13.10 Checklist before leaving site
- All slaves respond to an intentional Illegal Addr test with code 02.
- SCADA alarm list maps every ex-code to plain English.
- Gateway converts serial timeouts to code 0B.
- Client software caps retry bursts (≤ 1 req / 100 ms).
- Syslog/SNMP traps enabled for non-zero exception rate > 0.1 % of polls.
Chapter recap
- An exception frame is a built-in error packet—use it.
- MSB set + 1-byte code—easy to parse, easy to filter.
- Code→root-cause tables speed field repair dramatically.
- Smart clients distinguish “Illegal address” (fix config) from “Device busy” (just wait).
- Good gateways translate timeouts to 0B; good servers return the most specific code.
Assets to create
ID | Visual / asset |
---|---|
Fig-13-1 | Exception-code cheat wheel |
Fig-13-2 | Gateway timeout→exception flow |
Listing 1 | C exception builder |
Lab pcap | Capture with 01, 02, 03 errors |
Next up: Module 5 – Development & Implementation begins with Chapter 14 – Setting Up Your Modbus Lab: hardware shopping list, simulator walkthroughs, and serial-sniffer setups so you can practice everything you’ve learned.