YunaiV/yudao-cloud · error · IllegalArgumentException

非法的 conversationType: {}

Error message

非法的 conversationType: {}

What it means

ImRtcCallServiceImpl's create-call validation throws IllegalArgumentException when conversationType is neither the private nor the group value recognized by ImConversationTypeEnum.isPrivate/isGroup. This is the terminal fallback after the private branch (which validates peerUserId/inviteeIds) and the group branch (which requires groupId, non-empty inviteeIds and caller membership) — so the value is not merely wrong, it is unhandled entirely.

Source

Thrown at yudao-module-im/yudao-module-im-server/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java:868

            Long peerUserId = CollUtil.getFirst(reqVO.getInviteeIds());
            if (ObjUtil.equal(userId, peerUserId)) {
                throw exception(RTC_INVITE_SELF);
            }
            friendService.validateFriend(userId, peerUserId);
            return;
        }
        if (ImConversationTypeEnum.isGroup(conversationType)) {
            if (reqVO.getGroupId() == null) {
                throw exception(RTC_GROUP_REQUIRED);
            }
            // 群通话必须前端选中被邀请人(对齐微信);空集合直接拒
            if (CollUtil.isEmpty(reqVO.getInviteeIds())) {
                throw exception(RTC_GROUP_INVITEE_REQUIRED);
            }
            groupMemberService.validateMemberInGroup(reqVO.getGroupId(), userId);
            return;
        }
        throw new IllegalArgumentException("非法的 conversationType: " + conversationType);
    }

    /**
     * 解析被邀请池:私聊为 peerUserId 单元素;群聊为前端选中子集(超量抛错)
     *
     * @param reqVO     创建请求
     * @param inviterId 发起人编号;自己不进被邀请池
     * @return 被邀请人 userId 集合
     */
    private Set<Long> resolveInvitees(ImRtcCallCreateReqVO reqVO, Long inviterId) {
        // 1. 私聊:inviteeIds 已在 validateCreateCall 校验仅 1 个对端,直接复用
        if (ImConversationTypeEnum.isPrivate(reqVO.getConversationType())) {
            return new LinkedHashSet<>(reqVO.getInviteeIds());
        }

        // 2. 群聊校验:被邀请人必须是该群活跃成员,防止恶意客户端塞任意 userId
        groupMemberService.validateMembersInGroup(reqVO.getGroupId(), reqVO.getInviteeIds());
        Set<Long> initial = new LinkedHashSet<>(reqVO.getInviteeIds());

View on GitHub (pinned to 477be9dd49)

Solutions

  1. Send a conversationType defined by ImConversationTypeEnum (private value for 1v1 calls, group value for group calls)
  2. For group calls also pass groupId and a non-empty inviteeIds; for private calls pass the single peer
  3. Align app and server IM module versions

Example fix

// before
{"conversationType":0,"inviteeIds":[2]}

// after
{"conversationType":1,"peerUserId":2}            // private
// or
{"conversationType":2,"groupId":10,"inviteeIds":[2,3]} // group
Defensive patterns

Strategy: type-guard

Validate before calling

Integer ct = reqVO.getConversationType();
if (!ImConversationTypeEnum.isPrivate(ct) && !ImConversationTypeEnum.isGroup(ct)) {
    throw new IllegalArgumentException("conversationType 必须为 私聊 或 群聊");
}

Type guard

boolean isKnownConversationType(Integer ct) {
    return ImConversationTypeEnum.isPrivate(ct) || ImConversationTypeEnum.isGroup(ct);
}

Prevention

When it happens

Trigger: POST create RTC call with conversationType missing/null (falls through if not private), 0, or a future value like 'system'; frontend sending its own enum spelling ('single' instead of the numeric/constant the server expects); deserialization defaulting to 0 when the field is absent.

Common situations: Frontend/backend enum drift after an IM module upgrade; new conversation type added to the app before server support; JSON payload omitting conversationType so the field defaults.

Related errors


AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14). Data as JSON: /api/errors/ee858e12d693317f. Report an issue: GitHub.