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

  1. Ensure the client sends the tenant id header as a plain string or number scalar.
  2. Align the message converter so headers stay as String/Long rather than nested objects.
  3. 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

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.