Resolving S7-1200 Modbus TCP Error 8380 with PBSI MotorVision2

David Krause18 min read
ModbusSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

1. Problem Overview

A Siemens SIMATIC S7-1200 CPU (S7-1214 in this case, configured as a Modbus TCP client inside TIA Portal) cannot read input registers from a PBSI MotorVision2 (MV2) motor protection relay over Ethernet. The MB_CLIENT instruction toggles indefinitely between STATUS 7005, STATUS 7006, and STATUS 8380; the DONE output never goes TRUE; the ERROR output goes TRUE with STATUS 8380 ("Received Modbus frame has incorrect format or too few bytes were received") on every transaction cycle.

Network-layer checks are clean: the relay responds to a third-party Modbus scanner (CAS Modbus Scanner) on the same IP and port, returning valid register values. This proves the physical link, the IP/port configuration, the register address, and the data content are correct. The fault is therefore confined to the Modbus Application Protocol (MBAP) header produced by the relay's Modbus TCP server.

Key symptom pattern: STATUS 7005 → 7006 proves TCP CONNECT succeeded. 7006 → 8380 (with DONE = FALSE) proves the slave sent a reply that the S7-1200 MB_CLIENT parser rejected. This pattern is almost always a frame-format fault at the slave, not a configuration fault at the client.

2. System Configuration

Verified field configuration
Item Setting Notes
PLC SIMATIC S7-1214 DC/DC/DC (CPU 1214C, 6ES7214-1AG40-0XB0 family) Firmware V4.2 / V4.4 both reproduce the fault
Engineering TIA Portal V15.1 / V16 / V17 MB_CLIENT from "Communication > Other > Modbus TCP"
Modbus slave PBSI MotorVision2 (MV2) with Ethernet option Motor protection relay, see PBSI MotorVision2 product page
Slave serial settings (used by hardware path) Enabled / 19200 / Even parity Set per developer instructions even though the Ethernet path is used
Slave IP / port As assigned by network admin, TCP/502 Standard Modbus TCP port
Target register Input Register 30024 (4x reference, offset 0x0017) Function code 04 (Read Input Registers), LEN = 1 word
Reference tool CAS Modbus Scanner, ModScan, or Wireshark Reads the same register successfully

3. Status Code Interpretation on MB_CLIENT

The MB_CLIENT STATUS output is a 16-bit word. In this fault the values rotate as follows:

MB_CLIENT STATUS values observed
STATUS (decimal) Meaning (per Siemens S7-1200 manual collection) What it indicates in this case
7004 No job active / connection being torn down Initial idle state
7005 Processing connection establishment (TCP three-way handshake) Client opening TCP session to slave
7006 Connection established and monitored TCP session is up; first request being issued
8380 Received Modbus frame has incorrect format or too few bytes Reply arrived but MB_CLIENT parser rejected it

Per the SIMATIC S7-1200 communication manual, MB_CLIENT reports 8380 when the parser detects (a) a malformed MBAP header, (b) a function code other than the one requested, (c) a byte-count mismatch (response declares more bytes than follow), or (d) a length field that exceeds the TCP payload actually received. The fix in all four cases is the same: the slave must be made to emit a syntactically correct Modbus TCP PDU.

4. Modbus TCP MBAP Header Structure

Modbus TCP prepends a 7-byte MBAP header to every Protocol Data Unit (PDU). The header layout is fixed by the Modbus Organization's MODBUS Messaging on TCP/IP Implementation Guide V1.0b:

MBAP header field layout (7 bytes total)
Offset Size Field Description
0 2 bytes Transaction Identifier Echoed by slave; client uses it to match replies to requests
2 2 bytes Protocol Identifier 0x0000 for Modbus; any other value is invalid
4 2 bytes Length Number of bytes following this field (Unit ID + PDU). For a 1-word read response: 1 + 1 + 1 + 2 = 5
6 1 byte Unit Identifier Slave address (0x01..0xF7, 0xFF = broadcast on TCP)

The PDU (function code + data) follows the Unit ID. For a Read Input Registers reply reading N registers, the PDU is: 1 byte function code (0x04), 1 byte byte count (2 × N), then 2 × N bytes of register data. With the MBAP header, the total TCP payload is 7 + 1 + 1 + 2 × N = 9 + 2N bytes for an N-register read response.

Note: some vendors (and casual documentation) treat LEN as "number of data bytes" (i.e. 2 × N). Per the Modbus Organization specification, LEN counts from the Unit Identifier byte onwards. Both interpretations agree that LEN for one register is in the 2..5 range; both will reject a slave that puts 0x0006 in LEN for a 1-word reply.

5. Captured Frames

Captured with Wireshark on the same switch port; the request is unambiguous, the response is the focus of the fault.

Request (S7-1200 → MV2):

D7 26 00 00 00 06 FF 04 00 17 00 01
^^ ^^         ^^ ^^   ^^ ^^ ^^ ^^
TID          LEN UID  FC  StartAddr Qty
0xD726       0x0006 0xFF 0x04 0x0017  0x0001

Decode: Transaction ID = 0xD726, Protocol ID = 0x0000, Length = 6 (Unit ID + FC + Start Address + Quantity = 1 + 1 + 2 + 2 = 6, all correct), Unit ID = 0xFF, Function Code = 0x04 (Read Input Registers), Starting Address = 0x0017 (decimal 23, i.e. input register 30024), Quantity = 1 register. This request is byte-correct.

Response (MV2 → S7-1200), as emitted by the relay's firmware under fault:

MBAP : D7 26 00 00 00 06 FF
PDU  : 04 02 01 F4
0xD726  0x0006 0xFF 0x04 0x02 0x01F4 (= 500)

Observed data: the relay returns register value 0x01F4 = 500 (matches the CAS Modbus Scanner capture). The PDU content is correct: function code 0x04, byte count 0x02, payload 0x01F4.

Where the LENGTH field is wrong: the LEN field holds 0x0006 (6). For a 1-register read reply, the correct value is 0x0005 (1 Unit ID + 1 Function + 1 ByteCount + 2 data = 5). The relay's firmware is hard-coding the request LEN (6) into the response LEN (6), a classic copy-paste bug in the embedded Modbus TCP stack. The same fault is typical for FC 0x03, 0x04, 0x06, and 0x10 responses because the bug is in the LEN calculation, not in the function handler.

6. Root Cause: MBAP LENGTH Field Miscoded by Slave Firmware

When the S7-1200 MB_CLIENT parser receives the response, it does the following on the TCP payload:

  1. Read the 2-byte LEN field at offset 4 (= 6).
  2. Wait for the TCP stream to deliver LEN bytes (= 6 bytes) after the LEN field.
  3. Parse the 6 bytes as Unit ID (1) + Function Code (1) + ByteCount (1) + Data (3 bytes).

Step 3 fails because the slave only sent 4 bytes of PDU (FC + ByteCount + 2 data bytes). MB_CLIENT flags the discrepancy and latches ERROR with STATUS 8380 ("Received Modbus frame has incorrect format or too few bytes were received").

The slave is essentially saying "I sent you 3 register words (6 bytes), here they are" but only ever writes 1 word. From the S7-1200 perspective, 8380 is the only possible outcome of that contradiction.

Why error 8180 is sometimes quoted: STATUS 8180 ("Invalid request parameter" / "The request was rejected") appears in some Siemens revisions when the parser drops the transaction before the FC/byte-count check. Both 8180 and 8380 point to the same root cause: a frame whose declared LEN exceeds the bytes that actually arrived. If your TIA Portal build shows 8180 instead of 8380, you are looking at the same slave-side MBAP bug.

7. Diagnostic Procedure

Use this sequence to confirm the same fault on any S7-1200 ↔ third-party Modbus TCP slave link.

  1. Validate the slave from a known-good client. Run CAS Modbus Scanner, ModScan, or a small Python script with pymodbus.client.sync.ModbusTcpClient against the slave's IP/port and read the same register(s) the PLC needs. If the scanner reads the value correctly, the slave is electrically and register-wise healthy.
  2. Capture the exchange on the wire. Mirror the slave port to a laptop running Wireshark. Filter on tcp.port == 502. Trigger a single read from the S7-1200 by setting MB_CLIENT.REQ = TRUE for one cycle (use a one-shot rising-edge of a tag, not a level-driven REQ).
  3. Decode the MBAP header of the response. Expand the response packet → "Modbus/TCP" or "MBAP" → note the 2-byte Length field. For a read of N registers, the Length must equal 3 + 2N bytes per the spec. Verify against the table below.
Expected LEN values for FC 0x03 / FC 0x04 responses
Quantity of registers (N) PDU bytes Expected LEN field (decimal)
1 FC(1) + BC(1) + 2 = 4 5
2 FC(1) + BC(1) + 4 = 6 7
5 FC(1) + BC(1) + 10 = 12 13
10 FC(1) + BC(1) + 20 = 22 23
125 (max) FC(1) + BC(1) + 250 = 252 253
  1. Compare declared LEN to actual TCP payload size. If declared LEN > (TCP payload − 6), MB_CLIENT will fail with 8380 because it waits for bytes that never arrive. If declared LEN < (TCP payload − 6), the parser silently truncates the reply and your data DB holds a wrong value (no STATUS 8380, just garbage in the buffer). Both are equally bad — both point to a slave firmware bug.
  2. Eliminate the S7-1200 as a suspect by pointing MB_CLIENT at a known-good server. Run a Modbus TCP server simulator (Modbus Tools "Modbus Server", simplymodbus.ca TCP test server, or a Python ModbusTcpServer) on a laptop. Configure MB_CLIENT to the simulator's IP/port with the same MB_DB layout. If the PLC reads correctly against the simulator, the client code is fine and the fault is entirely in the slave.
  3. Sanity-check the scanner trace. Some Modbus scanners strip the MBAP header from the display and only show the PDU. If the captured response in Wireshark starts at 0x04 0x02 0x01 0xF4 but the scanner shows 0x01 0x04 0x02 0x01 0xF4, the scanner is prepending the Unit ID; the actual MBAP header is in Wireshark only. Compare the LEN field from Wireshark against the table above.

8. Solution: Vendor Firmware Fix

The only correct fix is for PBSI to patch the MV2 Modbus TCP stack so the response LEN field reflects the actual PDU length. Document the issue with:

  • Wireshark capture of request and response (PCAP file).
  • Decoded MBAP showing the discrepancy (request LEN = 6, response LEN = 6, expected 5 for 1 word).
  • The exact register, function code, and quantity requested.
  • PLC tag name, CPU order number (e.g. 6ES7214-1AG40-0XB0), and firmware version.
  • TIA Portal project version and MB_CLIENT instance name.

Ask the vendor to confirm the fixed firmware revision before installing it on the production relay. The vendor should supply release notes documenting the corrected LEN calculation for FC 0x03, 0x04, 0x06, and 0x10 (read/write multiple) responses, since the same copy-paste bug typically affects every FC the device supports.

Operational risk: firmware updates on protection relays must follow the site's outage procedure and protection-engineering sign-off. The MV2 is a protective device; an incorrect firmware flash or a power loss during flash can disable motor protection. Always verify the relay's self-test and protection pass after the update, and record the firmware revision in the relay's asset register.

9. Interim Workarounds (Until Firmware is Patched)

If you cannot wait for a vendor patch, the following workarounds restore functional reads at the cost of complexity or performance.

9.1 Insert a Modbus TCP Gateway / Protocol Converter

Deploy an intermediary that terminates the buggy MV2 frame and re-emits a correct Modbus TCP response to the S7-1200. Industrial options include:

  • Anybus X-gateway Modbus TCP Server → Modbus TCP Client bridge (acts as a slave to the S7-1200 and a master to the MV2, sanitizing the LEN field on egress).
  • B+B SmartWorx Vlinx MMR (Modbus messaging router) with a translation rule that rewrites the LEN field.
  • An embedded Linux box running a Python script with pymodbus.client.sync.ModbusTcpClient reading from the MV2, then writing the values into a local Modbus server that the S7-1200 polls with MB_CLIENT.

9.2 Use MB_RED_CLIENT with a Single Active Connection

The MB_RED_CLIENT instruction is functionally a superset of MB_CLIENT. In the S7-1200 manual collection it is documented as supporting "establish a connection between an S7-1200 CPU and a device that supports the Modbus TCP protocol" (MB_RED_CLIENT reference). It does not bypass the LEN validation in the parser — a slave that emits a wrong LEN field will still trigger 8380 on MB_RED_CLIENT. Its value here is that you can run two parallel connections to two different slaves simultaneously, which is useful if you have a spare MV2 or a second gateway.

9.3 Replace MB_CLIENT with Open User Communication (TCON / TSEND / TRCV)

As a last resort, replace MB_CLIENT with TCON, TSEND, and TRCV blocks and parse the MBAP header manually. You can correct for the LEN=6 miscoding by reading exactly 12 bytes (7 MBAP + 5 PDU) from TRCV regardless of what the header declares. This violates the Modbus spec but lets the process keep running.

// Pseudo-code for manual MBAP-tolerant parse
// MBAP header offset 0..6 (7 bytes)
// LEN field at offset 4..5 = 0x0006 (FAULT, should be 0x0005)
// Actual PDU is 5 bytes (Unit ID + FC + BC + 2 data)
// Fix: read exactly 12 bytes (7 MBAP + 5 PDU) from TRCV
TCON(REQ := tcon_req, ID := 1);                       // establish TCP
TSEND(REQ := send_req, ID := 1, LEN := 12,
      DATA := mbap_request);                          // 7 MBAP + 5 PDU
TRCV(EN_R := rcv_en, ID := 1, LEN := 12,
     DATA := recv_buffer);                            // hard 12 bytes
// Then validate TID at offset 0 matches the request TID
// and pull 0x01F4 from recv_buffer[9..10] as the register value.

10. MB_CLIENT Configuration Best Practices

These practices reduce the chance of misdiagnosing a slave-side bug as a PLC fault.

  1. One-shot REQ, not level-driven. Drive MB_CLIENT.REQ from the rising edge of a pulse tag, not from a sticky level. A level-driven REQ re-issues the request on every cycle, hiding intermittent faults and confusing diagnostic counters.
  2. Read MB_CLIENT.DONE and MB_CLIENT.ERROR as a pair. A "DONE never TRUE, ERROR never TRUE" state is a connection problem (check IP/port/firewall). "DONE never TRUE, ERROR TRUE with STATUS 8380" is a frame-format problem. Different root causes, different fixes.
  3. Use a non-optimized data block for the receive buffer. Optimized access hides the absolute byte offset of MB_CLIENT's data pointer, which makes Wireshark-to-DB mapping painful during commissioning. Disable "Optimized block access" on the instance DB during the bring-up phase.
  4. Size the receive DB to the maximum payload you will ever request. A 1-word request needs 2 bytes of data; a 125-word request needs 250 bytes. The MB_CLIENT data pointer must be large enough for the largest single read or the S7-1200 returns STATUS 80C8 / 8382.
  5. Set MB_UNIT_ID to 0xFF (255) for TCP slaves unless the slave's documentation requires a specific Unit ID. The Unit ID is preserved across TCP/serial gateways; for direct TCP slaves it is usually don't-care. Using the MB_CLIENT Connection_ID as the Unit_ID is incorrect: Connection_ID is a local block identifier and has no relationship to the on-wire Unit ID.
  6. Decouple the polling rate from the CPU scan cycle. Use a cyclic OB (e.g., OB35 at 100 ms) or a hardware timer ISR to gate REQ, not a cyclic flag at the OB1 scan rate. This prevents stack overflow on the slave if the CPU is faster than the slave's response time.
  7. Poll the relay under load for 24 hours with no 8380 STATUS. A clean 24-hour soak test is the standard acceptance criterion for any new Modbus integration.

11. Error Code Reference

Common MB_CLIENT STATUS values for S7-1200 / S7-1500
STATUS (decimal) Meaning Likely root cause / remedy
7000 No job active Idle; REQ not pulsed or job already completed
7001 First job executing Single-job MB_CLIENT in flight
7002 Second job executing Multi-job MB_CLIENT with two active requests
7003 Job canceled REQ dropped before completion; restart with rising edge
7004 No active job / connection idle Initial state after TCON or after DONE
7005 Processing connection establishment TCP handshake in progress; transient
7006 Connection established TCP session is up; awaiting slave reply
80C8 Read/write access denied by partner Slave rejected the request (e.g., illegal address, register protected)
80C9 Connection aborted by partner TCP RST or FIN from slave; check slave power and network
8180 Invalid request parameter / request rejected Pre-parse failure, often a malformed MBAP header
8380 Frame format error / too few bytes Slave LEN field, byte count, or FC inconsistent with payload
8381 Modbus exception code received Slave returned exception 01..04 (illegal function, illegal address, illegal data value, slave device failure)
8382 Invalid Modbus PDU Function code mismatch or illegal data address
8383 Read/write multiple quantity out of range Quantity exceeds Modbus PDU limit (125 registers / 2000 bits per request)

12. Verification

After the firmware fix or workaround, confirm correct operation with these checks:

  1. MB_CLIENT STATUS 0000 (or 7004 idle) and DONE = TRUE on every cycle. ERROR = FALSE, STATUS returns to idle.
  2. Wireshark capture shows LEN field = 0x0005 for the 1-word response. This is the structural confirmation that the slave is now emitting a spec-compliant frame.
  3. Data block contains the expected register value. Compare the WORD at offset 0 of the receive DB against the value read by CAS Modbus Scanner; they must match exactly.
  4. Trigger an out-of-range read and confirm exception handling. Request register 39999 (which does not exist on the MV2); the slave should return exception code 0x02 (illegal data address) and MB_CLIENT should report STATUS 8381. If it reports 8380 instead, the slave's exception path also has the LEN bug.
  5. 24-hour soak test with no 8380 STATUS. Continuous polling under normal process load; no transient ERROR, no DONE= FALSE cycles.

13. Alternate Controllers and Cross-Platform Notes

The same slave fault will produce different symptoms on different Modbus TCP stacks:

Cross-platform symptom mapping for the same MV2 LEN bug
Controller / stack Typical symptom Detection method
Siemens S7-1200 MB_CLIENT STATUS 8380 (or 8180), DONE = FALSE, ERROR = TRUE MB_CLIENT.STATUS, MB_CLIENT.ERROR
Siemens S7-1500 MB_CLIENT STATUS 8380, DONE = FALSE, ERROR = TRUE Same tag set as S7-1200
Schneider Modicon M340 BMX NOE 0100 (Modbus TCP scanner) Communication error bit; no register update Watch %MW or diagnostic registers; check NOE web page for last error
Allen-Bradley CompactLogix / ControlLogix with MSG instruction MSG.ER bit set, extended error code 0x000F (transport error) MSG instruction error word, Studio 5000 Logix Designer
Python pymodbus 3.x ModbusIOException or silent truncation, depending on slave-mode flag Wireshark trace; pymodbus logger output
Modbus Poll / ModScan Often reads the value but flags "Check Sum" or "Invalid Response" depending on parser leniency Poll/Diag window

The root cause is the same on every platform: the slave's LEN field is wrong. The fix is the same on every platform: get the slave firmware patched. The diagnostic method (Wireshark on TCP/502) is also the same on every platform.

14. Commissioning Checklist for a New Modbus TCP Slave

  1. Verify the slave's IP and port are reachable with ping and telnet <ip> 502.
  2. Read at least one register with a third-party Modbus scanner (CAS Modbus Scanner, ModScan, or pymodbus). Confirm the value is plausible against the device's documentation.
  3. Capture the request/response exchange with Wireshark. Decode the MBAP header. Confirm the LEN field matches the expected value for the read quantity.
  4. Configure MB_CLIENT in TIA Portal with the same IP, port, Unit ID, register address, and length. Use a non-optimized DB. Pulse REQ from a one-shot edge.
  5. Verify DONE = TRUE and the receive DB holds the expected value.
  6. Add STATUS 8380, 80C8, 80C9 to a HMI alarm page so operators can see the failure mode.
  7. Run a 24-hour soak test before declaring the link production-ready.

FAQ

What does S7-1200 MB_CLIENT STATUS 8380 mean?

STATUS 8380 is the S7-1200 Modbus TCP client's response to a frame whose declared MBAP length, byte count, or function code does not match the bytes that actually arrived in the TCP payload. Per the SIMATIC S7-1200 communication manual, the most common cause is a slave that miscodes the MBAP Length field, the function-code byte, or the byte-count byte in the PDU.

Why do I see 7005 and 7006 before 8380 on the MB_CLIENT block?

7005 indicates the TCP connection is being established (three-way handshake in progress) and 7006 indicates the connection is established. The cycle 7005 → 7006 → 8380 proves the TCP session succeeded but the slave's Modbus PDU failed the parser checks. If you never reach 7006, the fault is at the TCP layer (IP, port, firewall, slave powered off) rather than at the Modbus application layer.

Can the S7-1200 work around a buggy slave MBAP header?

Not with the standard MB_CLIENT or MB_RED_CLIENT instructions, because both perform spec-compliant MBAP parsing and reject any frame whose declared length exceeds the bytes actually delivered. To work around a slave bug you must either deploy a protocol-translating gateway in front of the slave or replace MB_CLIENT with manual TCON/TSEND/TRCV blocks and a custom parser that ignores the LEN field. Both options are inferior to fixing the slave firmware.

Does the MB_RED_CLIENT instruction behave differently from MB_CLIENT for this fault?

No. MB_RED_CLIENT is a redundant variant of MB_CLIENT; it manages two parallel TCP connections for failover but uses the same MBAP parser. A slave that emits a wrong LEN field will trigger the same 8380 on MB_RED_CLIENT. Reference: MB_RED_CLIENT in the S7-1200 manual collection.

Is STATUS 8180 the same as STATUS 8380?

Both point to a malformed or rejected frame, but they are emitted at different stages of the parser. 8180 is a parameter-validation failure raised before the LEN field is consumed; 8380 is a post-parse failure raised when the declared LEN does not match the bytes that followed. If the LEN field is set before the function code is examined, you may see 8180 on some firmware revisions and 8380 on others. Either way, the slave's MBAP encoding is the fault.

Why does CAS Modbus Scanner read the relay but the S7-1200 cannot?

Most third-party Modbus scanners are more lenient than the S7-1200 MB_CLIENT parser: they will accept a reply whose declared MBAP length exceeds the byte count, or they will pre-empt the LEN with a strict byte-count read. CAS Modbus Scanner, ModScan, and pymodbus in default mode all read the data even when the LEN field is wrong. The S7-1200 parser is spec-strict and refuses the same frame. This is a useful diagnostic signal: if a scanner reads the slave and the S7-1200 does not, the slave's MBAP encoding is almost always the cause.

Back to blog