YunaiV/ruoyi-vue-pro · error · IllegalArgumentException
不支持的功能码: {}
Error message
不支持的功能码: {} What it means
createReadRequest() only accepts the four Modbus read function codes: FC1 (read coils), FC2 (read discrete inputs), FC3 (read holding registers), FC4 (read input registers). Any other integer value hits the default branch and throws IllegalArgumentException. This means the point/device config supplied a functionCode outside {1,2,3,4} for a read operation.
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:141
});
}
/**
* 创建读取请求
*/
@SuppressWarnings("EnhancedSwitchMigration")
private static ModbusRequest createReadRequest(Integer functionCode, Integer address, Integer count) {
switch (functionCode) {
case FC_READ_COILS:
return new ReadCoilsRequest(address, count);
case FC_READ_DISCRETE_INPUTS:
return new ReadInputDiscretesRequest(address, count);
case FC_READ_HOLDING_REGISTERS:
return new ReadMultipleRegistersRequest(address, count);
case FC_READ_INPUT_REGISTERS:
return new ReadInputRegistersRequest(address, count);
default:
throw new IllegalArgumentException("不支持的功能码: " + functionCode);
}
}
/**
* 创建写入请求
*/
@SuppressWarnings("EnhancedSwitchMigration")
private static ModbusRequest createWriteRequest(Integer functionCode, Integer address, Integer count, int[] values) {
switch (functionCode) {
case FC_READ_COILS: // 写线圈(使用功能码 5 或 15)
if (count == 1) {
return new WriteCoilRequest(address, values[0] != 0);
} else {
BitVector bv = new BitVector(count);
for (int i = 0; i < Math.min(values.length, count); i++) {
bv.setBit(i, values[i] != 0);
}
return new WriteMultipleCoilsRequest(address, bv);View on GitHub (pinned to 0418084e22)
Solutions
- Set the point functionCode to 1, 2, 3, or 4 (the standard Modbus read codes) per the device register map.
- Add config-load validation rejecting points whose functionCode is not in {1,2,3,4} for read points.
- If the device uses a custom function code (e.g. FC65), use a protocol variant that supports it (the Modbus TCP Server protocol uses a custom FC for auth) rather than the generic read path.
Defensive patterns
Strategy: validation
Validate before calling
// before reading, ensure the function code is a supported read code
if (functionCode == null || functionCode < 1 || functionCode > 4) {
throw new IllegalArgumentException("读取功能码必须在 1-4 之间, 当前: " + functionCode);
} Type guard
boolean isSupportedReadFc(Integer fc) {
return fc != null && fc >= 1 && fc <= 4;
} Prevention
- Validate functionCode at device-config load time, rejecting points outside {1,2,3,4} for reads.
- Default functionCode to a sane value (3 = holding registers) rather than 0.
- Add a config integrity unit test that asserts all point function codes are valid for their access direction.
When it happens
Trigger: point.getFunctionCode() returns a write FC (5,6,15,16), 0 (default/unset), null auto-unboxed to NPE (caught upstream then re-wrapped), or any non-standard code; a read is then attempted.
Common situations: Device config accidentally uses a write function code for a read point; functionCode column defaulted to 0 in the DB; vendor uses a non-standard/custom function code for reads.
Related errors
- 功能码 {} 不支持写操作
- [createProtocol][协议实例 %s 的协议类型 %s 暂不支持]
- Modbus 读取失败 [slaveId=%d, identifier=%s, functionCode=%d, add
- Modbus 写入失败 [slaveId=%d, identifier=%s, address=%d]
- [startTcpServer][TCP Server 启动失败]
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/a5bcc8bea8f5cc99.
Report an issue: GitHub.