YunaiV/ruoyi-vue-pro · error · IllegalArgumentException
未知的数据类型:{}
Error message
未知的数据类型:{} What it means
This is a patched Spring InvocableHandlerMethod that resolves a tenantId argument from a message header. It handles Long, Number, String, and byte[]; any other type (e.g. an Integer[] return, a Map, a JSON object, or a deserialized custom type) hits the else and throws IllegalArgumentException. It indicates the message header carried a value of an unsupported Java type.
Source
Thrown at yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java:149
private Long parseTenantId(Message<?> message) {
Object tenantId = message.getHeaders().get(HEADER_TENANT_ID);
if (tenantId == null) {
return null;
}
if (tenantId instanceof Long) {
return (Long) tenantId;
}
if (tenantId instanceof Number) {
return ((Number) tenantId).longValue();
}
if (tenantId instanceof String) {
return Long.parseLong((String) tenantId);
}
if (tenantId instanceof byte[]) {
return Long.parseLong(new String((byte[]) tenantId));
}
throw new IllegalArgumentException("未知的数据类型:" + tenantId);
}
/**
* Get the method argument values for the current message, checking the provided
* argument values and falling back to the configured argument resolvers.
* <p>The resulting array will be passed into {@link #doInvoke}.
* @since 5.1.2
*/
protected Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);View on GitHub (pinned to 0418084e22)
Solutions
- Ensure the client sends the tenant id header as a plain string or number scalar.
- Align the message converter so headers stay as String/Long rather than nested objects.
- If a wider type set is expected, extend the patched conversion to handle the additional type safely.
Example fix
// before: client sends tenant as object header {"tenantId":{"v":1}}
// after: send a scalar string header
tenantId: "1" Defensive patterns
Strategy: type-guard
Validate before calling
Object h = message.getHeaders().get("tenantId");
if (!(h instanceof Long || h instanceof Number || h instanceof String || h instanceof byte[]))
throw new IllegalArgumentException("tenantId header must be scalar, got " + h.getClass()); Type guard
static boolean isSupportedTenantType(Object v) { return v instanceof Long || v instanceof Number || v instanceof String || v instanceof byte[]; } Try / catch
try { return convertTenantId(header); }
catch (IllegalArgumentException e) { rejectMessage("unsupported tenantId type"); return null; } Prevention
- Send tenantId as a scalar string header from clients
- Keep message converters consistent client/server
- Extend the patched converter only with safe, well-defined types
When it happens
Trigger: A messaging (WebSocket/STOMP/Simp) handler declares a Long tenantId parameter but the incoming message header contains a non-convertible type (a JSON object, a list, an Integer array, or a boolean). Serializer config mismatch between client and server.
Common situations: Client sends tenant as a JSON object/array instead of a scalar; a message converter that deserializes headers into POJOs; protocol upgrade where the tenant header format changed.
Related errors
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/1509049c168e1a77.
Report an issue: GitHub.