YunaiV/ruoyi-vue-pro · error · RuntimeException
Modbus 读取失败 [slaveId=%d, identifier=%s, functionCode=%d, add
Error message
Modbus 读取失败 [slaveId=%d, identifier=%s, functionCode=%d, address=%d, count=%d]
What it means
Wraps ANY exception thrown during a Modbus TCP read transaction inside the connection's executeBlocking block: createReadRequest, transaction.execute(), or extractValues. j2mod's ModbusTCPTransaction throws on TCP connection loss, slave timeout, a Modbus exception response (illegal function/address/data value), or when the response object cannot be cast to the expected response subclass. The wrapping preserves slaveId/identifier/functionCode/address/count for diagnosis.
Source
Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbus/common/utils/IotModbusTcpClientUtils.java:85
Integer registerAddress,
Integer registerCount,
String identifier) {
return connection.executeBlocking(tcpConnection -> {
try {
// 1. 创建请求
ModbusRequest request = createReadRequest(functionCode, registerAddress, registerCount);
request.setUnitID(slaveId);
// 2. 执行事务(请求)
ModbusTCPTransaction transaction = new ModbusTCPTransaction(tcpConnection);
transaction.setRequest(request);
transaction.execute();
// 3. 解析响应
ModbusResponse response = transaction.getResponse();
return extractValues(response, functionCode);
} catch (Exception e) {
throw new RuntimeException(String.format("Modbus 读取失败 [slaveId=%d, identifier=%s, functionCode=%d, address=%d, count=%d]",
slaveId, identifier, functionCode, registerAddress, registerCount), e);
}
});
}
/**
* 写入 Modbus 数据
*
* @param connection Modbus 连接
* @param slaveId 从站地址
* @param point 点位配置
* @param values 要写入的值
* @return 是否成功
*/
public static Future<Boolean> write(IotModbusTcpClientConnectionManager.ModbusConnection connection,
Integer slaveId,
IotModbusPointRespDTO point,
int[] values) {View on GitHub (pinned to 0418084e22)
Solutions
- Inspect the wrapped cause (RuntimeException.getCause()) — a j2mod ExceptionResponse / ModbusException tells whether it is a slave exception (illegal address) vs network (connection reset).
- Verify the device is online and the TCP connection is up; ping/Telnet the device.
- Confirm slaveId, registerAddress, registerCount and functionCode against the device's register map datasheet.
- Reproduce with an independent Modbus tool (e.g. modpoll, QModMaster) reading the same slaveId/address/FC to isolate gateway vs device.
- Tune j2mod transaction timeout/retries if the device is slow.
Defensive patterns
Strategy: try-catch
Validate before calling
// before reading, confirm the connection is alive and the FC/address are valid
if (!connection.isOpen()) {
return Future.failedFuture(new IllegalStateException("Modbus 连接未打开"));
}
if (functionCode == null || functionCode < 1 || functionCode > 4) {
return Future.failedFuture(new IllegalArgumentException("读取功能码非法: " + functionCode));
} Type guard
// valid read function codes only
boolean isValidReadFc(Integer fc) {
return fc != null && fc >= 1 && fc <= 4;
} Try / catch
// handle read failure on the returned Future; classify transient vs permanent
IotModbusTcpClientUtils.read(connection, slaveId, point)
.onFailure(e -> {
Throwable root = e.getCause() != null ? e.getCause() : e;
if (root instanceof java.net.SocketException || root instanceof java.net.SocketTimeoutException) {
// transient — schedule a retry after backoff
} else {
// permanent (illegal address / slave exception) — mark point as error, alert
}
}); Prevention
- Validate the device register map (slaveId/address/FC/count) against the datasheet before enabling polling.
- Set a j2mod transaction timeout appropriate to the slowest device.
- Implement retry-with-backoff for transient network drops; cap retries to avoid read storms.
- Monitor per-point read failure rates and disable chronic offenders automatically.
When it happens
Trigger: Slave device offline or TCP connection dropped; wrong slaveId; registerAddress/count out of the device's valid range; function code not implemented by the slave; network interruption mid-transaction; slave returns a Modbus exception code (e.g. 0x83 = illegal function on FC3).
Common situations: Device powered off; misconfigured slaveId or register map; flaky serial-to-TCP converter; polling a register the device does not expose; device reboot during poll; j2mod transaction timeout too short for a slow instrument.
Related errors
- Modbus 写入失败 [slaveId=%d, identifier=%s, address=%d]
- MQTT Client 启动失败: 连接 Broker 失败
- 功能码 {} 不支持写操作
- [startTcpServer][TCP Server 启动失败]
- [createProtocol][协议实例 %s 的协议类型 %s 暂不支持]
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/61cad83d60a7fa4e.
Report an issue: GitHub.