GEMMA DEVELOPER AGENTSAVED EVIDENCE
← Dataset Exploration
ARCHIVED TRAINING / pymodbus-dev/pymodbus

pymodbus-dev__pymodbus-1923

This is a preserved training example. Membership in the current training wave has not been verified.
pymodbus-dev/pymodbus · Task 123 of 169

Problem statement

Pymodbus doesn't correctly handle Reassembled TCP segments
### Versions

- Python: Python: 3.11.4
- OS: Ubuntu 20.04
- Pymodbus: pymodbus-3.7.0.dev0  (git commit 81df5b1cde349dddd32ac3c1fd97ec4b475c2512) as well as 3.5.4
- Modbus Hardware (if used): SMA STP 6000TL-20 (version 02.51.02.R)

### Pymodbus Specific
- Client: tcp - async

### Description

When trying to read registers from the SMA STP 6000TL Inverter, the Modbus Response is split over 2 frames where the second frame only contains the last required byte. pymodbus doesn't seem to reassemble the modbus frames and instead tries parsing the first frame as a modbus response which it discards because it doesn't pass the Frame check. It then tries reading the second frame (consisting of only one byte) as a response and throws an exception because it can't decode it.

pymodbus should probably check the length of the tcp packet and only run the frame check once the complete packet has arrived. I've attached the client code, pymodbus logs and a wireshark capture of the modbus traffic.

### Code and Logs
[20240104_tcp_reassembly.pcapng.gz](https://github.com/pymodbus-dev/pymodbus/files/13828939/20240104_tcp_reassembly.pcapng.gz)

```python
import asyncio

import pymodbus
from pymodbus.client import AsyncModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.exceptions import ModbusException
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.pdu import ExceptionResponse

pymodbus.pymodbus_apply_logging_config("DEBUG")


async def main():
    async with AsyncModbusTcpClient(
        host="127.0.0.1", port=5502, reconnect_delay=0
    ) as mbus:
        response = await mbus.read_holding_registers(42109, 4, slave=1)
        decoder = BinaryPayloadDecoder.fromRegisters(
            response.registers, byteorder=Endian.BIG, wordorder=Endian.BIG
        )
        _serial = decoder.decode_32bit_uint()
        _susy_id = decoder.decode_16bit_uint()
        unit_id = decoder.decode_16bit_uint()


if __name__ == "__main__":
    asyncio.run(main())
```
Logs:
```
2024-01-04 11:16:16,385 DEBUG logging:103 Connecting to 127.0.0.1:5502.
2024-01-04 11:16:16,385 DEBUG logging:103 Connecting comm
2024-01-04 11:16:16,385 DEBUG logging:103 Connected to comm
2024-01-04 11:16:16,385 DEBUG logging:103 callback_connected called
2024-01-04 11:16:16,385 DEBUG logging:103 send: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x3 0xa4 0x7d 0x0 0x4
2024-01-04 11:16:16,385 DEBUG logging:103 Adding transaction 1
2024-01-04 11:16:16,635 DEBUG logging:103 recv: 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0 old_data:  addr=None
2024-01-04 11:16:16,635 DEBUG logging:103 Processing: 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0
2024-01-04 11:16:16,635 DEBUG logging:103 Frame check failed, ignoring!!
2024-01-04 11:16:16,635 DEBUG logging:103 Resetting frame - Current Frame in buffer - 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0
2024-01-04 11:16:16,719 DEBUG logging:103 recv: 0x3 old_data:  addr=None
2024-01-04 11:16:16,719 DEBUG logging:103 Processing: 0x3
2024-01-04 11:16:16,719 DEBUG logging:103 Factory Response[ReadHoldingRegistersResponse': 3]
2024-01-04 11:16:16,719 ERROR logging:115 General exception: index out of range
2024-01-04 11:16:16,719 DEBUG logging:103 Resetting frame - Current Frame in buffer - 0x3
Fatal error: protocol.data_received() call failed.
protocol: <pymodbus.client.tcp.AsyncModbusTcpClient object at 0x7fa70e325f70>
transport: <_SelectorSocketTransport fd=6 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/lib/python3.8/asyncio/selector_events.py", line 862, in _read_ready__data_received
    self._protocol.data_received(data)
  File "/home/simon/tools/pymodbus/pymodbus/transport/transport.py", line 318, in data_received
    self.datagram_received(data, None)
  File "/home/simon/tools/pymodbus/pymodbus/transport/transport.py", line 352, in datagram_received
    cut = self.callback_data(self.recv_buffer, addr=addr)
  File "/home/simon/tools/pymodbus/pymodbus/client/base.py", line 186, in callback_data
    self.framer.processIncomingPacket(data, self._handle_response, slave=0)
  File "/home/simon/tools/pymodbus/pymodbus/framer/base.py", line 139, in processIncomingPacket
    self.frameProcessIncomingPacket(single, callback, slave, **kwargs)
  File "/home/simon/tools/pymodbus/pymodbus/framer/socket_framer.py", line 136, in frameProcessIncomingPacket
    self._process(callback, tid, error=True)
  File "/home/simon/tools/pymodbus/pymodbus/framer/socket_framer.py", line 154, in _process
    raise ModbusIOException("Unable to decode request")
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request
2024-01-04 11:16:16,721 DEBUG logging:103 Connection lost comm due to Modbus Error: [Input/Output] Unable to decode request
2024-01-04 11:16:16,721 DEBUG logging:103 Getting transaction 1
Traceback (most recent call last):
  File "bug_reproducer.py", line 27, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "bug_reproducer.py", line 17, in main
    response = await mbus.read_holding_registers(42109, 4, slave=1)
  File "/home/simon/tools/pymodbus/pymodbus/client/base.py", line 167, in async_execute
    resp = await asyncio.wait_for(
  File "/usr/lib/python3.8/asyncio/tasks.py", line 494, in wait_for
    return fut.result()
pymodbus.exceptions.ConnectionException: Modbus Error: [Connection] Connection lost during request
```

Training membership

opd_e4b_pure_v6a opd_e4b_pure_v6b opd_e4b_pure_v7 opd_e4b_pure_v7b

Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.

Task and snapshot provenance

Snapshot captured 2026-11-12T17:06:59.476467+00:00 · Autoresearch-Arena/gemma-4-developer-agent

{
  "datasets": [
    "opd_e4b_pure_v6a",
    "opd_e4b_pure_v6b",
    "opd_e4b_pure_v7",
    "opd_e4b_pure_v7b"
  ],
  "examples": 9,
  "instance_id": "pymodbus-dev__pymodbus-1923",
  "problem_statement": "Pymodbus doesn't correctly handle Reassembled TCP segments\n### Versions\r\n\r\n- Python: Python: 3.11.4\r\n- OS: Ubuntu 20.04\r\n- Pymodbus: pymodbus-3.7.0.dev0  (git commit 81df5b1cde349dddd32ac3c1fd97ec4b475c2512) as well as 3.5.4\r\n- Modbus Hardware (if used): SMA STP 6000TL-20 (version 02.51.02.R)\r\n\r\n### Pymodbus Specific\r\n- Client: tcp - async\r\n\r\n### Description\r\n\r\nWhen trying to read registers from the SMA STP 6000TL Inverter, the Modbus Response is split over 2 frames where the second frame only contains the last required byte. pymodbus doesn't seem to reassemble the modbus frames and instead tries parsing the first frame as a modbus response which it discards because it doesn't pass the Frame check. It then tries reading the second frame (consisting of only one byte) as a response and throws an exception because it can't decode it.\r\n\r\npymodbus should probably check the length of the tcp packet and only run the frame check once the complete packet has arrived. I've attached the client code, pymodbus logs and a wireshark capture of the modbus traffic.\r\n\r\n### Code and Logs\r\n[20240104_tcp_reassembly.pcapng.gz](https://github.com/pymodbus-dev/pymodbus/files/13828939/20240104_tcp_reassembly.pcapng.gz)\r\n\r\n```python\r\nimport asyncio\r\n\r\nimport pymodbus\r\nfrom pymodbus.client import AsyncModbusTcpClient\r\nfrom pymodbus.constants import Endian\r\nfrom pymodbus.exceptions import ModbusException\r\nfrom pymodbus.payload import BinaryPayloadDecoder\r\nfrom pymodbus.pdu import ExceptionResponse\r\n\r\npymodbus.pymodbus_apply_logging_config(\"DEBUG\")\r\n\r\n\r\nasync def main():\r\n    async with AsyncModbusTcpClient(\r\n        host=\"127.0.0.1\", port=5502, reconnect_delay=0\r\n    ) as mbus:\r\n        response = await mbus.read_holding_registers(42109, 4, slave=1)\r\n        decoder = BinaryPayloadDecoder.fromRegisters(\r\n            response.registers, byteorder=Endian.BIG, wordorder=Endian.BIG\r\n        )\r\n        _serial = decoder.decode_32bit_uint()\r\n        _susy_id = decoder.decode_16bit_uint()\r\n        unit_id = decoder.decode_16bit_uint()\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    asyncio.run(main())\r\n```\r\nLogs:\r\n```\r\n2024-01-04 11:16:16,385 DEBUG logging:103 Connecting to 127.0.0.1:5502.\r\n2024-01-04 11:16:16,385 DEBUG logging:103 Connecting comm\r\n2024-01-04 11:16:16,385 DEBUG logging:103 Connected to comm\r\n2024-01-04 11:16:16,385 DEBUG logging:103 callback_connected called\r\n2024-01-04 11:16:16,385 DEBUG logging:103 send: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x3 0xa4 0x7d 0x0 0x4\r\n2024-01-04 11:16:16,385 DEBUG logging:103 Adding transaction 1\r\n2024-01-04 11:16:16,635 DEBUG logging:103 recv: 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0 old_data:  addr=None\r\n2024-01-04 11:16:16,635 DEBUG logging:103 Processing: 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0\r\n2024-01-04 11:16:16,635 DEBUG logging:103 Frame check failed, ignoring!!\r\n2024-01-04 11:16:16,635 DEBUG logging:103 Resetting frame - Current Frame in buffer - 0x0 0x1 0x0 0x0 0x0 0xb 0x1 0x3 0x8 0x0 0xb5 0x12 0x2f 0x37 0x21 0x0\r\n2024-01-04 11:16:16,719 DEBUG logging:103 recv: 0x3 old_data:  addr=None\r\n2024-01-04 11:16:16,719 DEBUG logging:103 Processing: 0x3\r\n2024-01-04 11:16:16,719 DEBUG logging:103 Factory Response[ReadHoldingRegistersResponse': 3]\r\n2024-01-04 11:16:16,719 ERROR logging:115 General exception: index out of range\r\n2024-01-04 11:16:16,719 DEBUG logging:103 Resetting frame - Current Frame in buffer - 0x3\r\nFatal error: protocol.data_received() call failed.\r\nprotocol: <pymodbus.client.tcp.AsyncModbusTcpClient object at 0x7fa70e325f70>\r\ntransport: <_SelectorSocketTransport fd=6 read=polling write=<idle, bufsize=0>>\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/python3.8/asyncio/selector_events.py\", line 862, in _read_ready__data_received\r\n    self._protocol.data_received(data)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/transport/transport.py\", line 318, in data_received\r\n    self.datagram_received(data, None)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/transport/transport.py\", line 352, in datagram_received\r\n    cut = self.callback_data(self.recv_buffer, addr=addr)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/client/base.py\", line 186, in callback_data\r\n    self.framer.processIncomingPacket(data, self._handle_response, slave=0)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/framer/base.py\", line 139, in processIncomingPacket\r\n    self.frameProcessIncomingPacket(single, callback, slave, **kwargs)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/framer/socket_framer.py\", line 136, in frameProcessIncomingPacket\r\n    self._process(callback, tid, error=True)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/framer/socket_framer.py\", line 154, in _process\r\n    raise ModbusIOException(\"Unable to decode request\")\r\npymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request\r\n2024-01-04 11:16:16,721 DEBUG logging:103 Connection lost comm due to Modbus Error: [Input/Output] Unable to decode request\r\n2024-01-04 11:16:16,721 DEBUG logging:103 Getting transaction 1\r\nTraceback (most recent call last):\r\n  File \"bug_reproducer.py\", line 27, in <module>\r\n    asyncio.run(main())\r\n  File \"/usr/lib/python3.8/asyncio/runners.py\", line 44, in run\r\n    return loop.run_until_complete(main)\r\n  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 616, in run_until_complete\r\n    return future.result()\r\n  File \"bug_reproducer.py\", line 17, in main\r\n    response = await mbus.read_holding_registers(42109, 4, slave=1)\r\n  File \"/home/simon/tools/pymodbus/pymodbus/client/base.py\", line 167, in async_execute\r\n    resp = await asyncio.wait_for(\r\n  File \"/usr/lib/python3.8/asyncio/tasks.py\", line 494, in wait_for\r\n    return fut.result()\r\npymodbus.exceptions.ConnectionException: Modbus Error: [Connection] Connection lost during request\r\n```",
  "repo": "pymodbus-dev/pymodbus",
  "source": "v2/experiments/train_data/opd_e4b_pure_v6a/verified_rft_messages.jsonl",
  "source_sha256": "f045b7ca5b3883a1e2eaee81e1c02a4a1b53dd7b7b36e98bacb2ba5823a15148"
}
{
  "captured_at": "2026-11-12T17:06:59.476467+00:00",
  "membership": "archived training",
  "membership_evidence": "Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.",
  "name": "Preserved post-training task archive",
  "source": "Autoresearch-Arena/gemma-4-developer-agent",
  "source_revision": "016496de222aaafca0d4ee4c18efc63ba616f76e",
  "sources": [
    {
      "path": "v2/experiments/train_data/opd_e4b_cispo_v5/verified_rft_messages.jsonl",
      "sha256": "a43610ad0dfb6ace95375cfae09000f41afc0338cc925af870a4ade7a9b20c4c"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_hybrid_v3/verified_rft_messages.jsonl",
      "sha256": "bd326303eb127e8e5e08f03daf97bb88d79d19709d59f3f93f348bc56686a8df"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_onpolicy_v3/verified_rft_messages.jsonl",
      "sha256": "960c680e797e823a0d3a22f4b1d5ef60a72971373d703b877340b0c9126aaf68"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6a/verified_rft_messages.jsonl",
      "sha256": "f045b7ca5b3883a1e2eaee81e1c02a4a1b53dd7b7b36e98bacb2ba5823a15148"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6b/verified_rft_messages.jsonl",
      "sha256": "0f62460a9706eea5e1605255896f191ab00cb5706c5f1f2e1c293e9a718218dc"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7/verified_rft_messages.jsonl",
      "sha256": "e37f7bd675322f3f81500b73559d60d5f602ca0537bf19f5cb06332c728c7b72"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7b/verified_rft_messages.jsonl",
      "sha256": "b864bdc8695183433eef6e31cb8d33fad44ba3aded2170c1ade4ad5b2944ce23"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_self_audit_v4/verified_rft_messages.jsonl",
      "sha256": "0026023745afb8f3dc1c176dc7f7171157b4ad5a66656b524af218e8e19ceee6"
    },
    {
      "path": "v2/experiments/train_data/rft_e4b_aligned_v2/verified_rft_messages.jsonl",
      "sha256": "92a4515fee9d152b0d4c510ee3ce4caaaffe2003ba7584469f8027f174aab18c"
    },
    {
      "path": "v2/experiments/train_data/rft_v1/verified_rft_messages.jsonl",
      "sha256": "a42453ccd7ac7680b0a03865e8e7080bc8bf74c8d9d193b440c441ed46f8512b"
    },
    {
      "path": "v2/experiments/train_data/rft_v2/verified_rft_messages.jsonl",
      "sha256": "18f4b3bd7e651f83c6acab479c9475e3fa50dc652a384f309e97146983ac85ba"
    }
  ]
}