{"record":{"id":"ee858e12d693317f","repo":"YunaiV/yudao-cloud","slug":"conversationtype","errorCode":null,"errorMessage":"非法的 conversationType: {}","messagePattern":"非法的 conversationType: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":500,"severity":"error","filePath":"yudao-module-im/yudao-module-im-server/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java","lineNumber":868,"sourceCode":"            Long peerUserId = CollUtil.getFirst(reqVO.getInviteeIds());\n            if (ObjUtil.equal(userId, peerUserId)) {\n                throw exception(RTC_INVITE_SELF);\n            }\n            friendService.validateFriend(userId, peerUserId);\n            return;\n        }\n        if (ImConversationTypeEnum.isGroup(conversationType)) {\n            if (reqVO.getGroupId() == null) {\n                throw exception(RTC_GROUP_REQUIRED);\n            }\n            // 群通话必须前端选中被邀请人（对齐微信）；空集合直接拒\n            if (CollUtil.isEmpty(reqVO.getInviteeIds())) {\n                throw exception(RTC_GROUP_INVITEE_REQUIRED);\n            }\n            groupMemberService.validateMemberInGroup(reqVO.getGroupId(), userId);\n            return;\n        }\n        throw new IllegalArgumentException(\"非法的 conversationType: \" + conversationType);\n    }\n\n    /**\n     * 解析被邀请池：私聊为 peerUserId 单元素；群聊为前端选中子集（超量抛错）\n     *\n     * @param reqVO     创建请求\n     * @param inviterId 发起人编号；自己不进被邀请池\n     * @return 被邀请人 userId 集合\n     */\n    private Set<Long> resolveInvitees(ImRtcCallCreateReqVO reqVO, Long inviterId) {\n        // 1. 私聊：inviteeIds 已在 validateCreateCall 校验仅 1 个对端，直接复用\n        if (ImConversationTypeEnum.isPrivate(reqVO.getConversationType())) {\n            return new LinkedHashSet<>(reqVO.getInviteeIds());\n        }\n\n        // 2. 群聊校验：被邀请人必须是该群活跃成员，防止恶意客户端塞任意 userId\n        groupMemberService.validateMembersInGroup(reqVO.getGroupId(), reqVO.getInviteeIds());\n        Set<Long> initial = new LinkedHashSet<>(reqVO.getInviteeIds());","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/YunaiV/yudao-cloud/blob/477be9dd49ab7223a972a6abdff0684d6423dec3/yudao-module-im/yudao-module-im-server/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java#L850-L886","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Send a conversationType defined by ImConversationTypeEnum (private value for 1v1 calls, group value for group calls)","For group calls also pass groupId and a non-empty inviteeIds; for private calls pass the single peer","Align app and server IM module versions"],"exampleFix":"// before\n{\"conversationType\":0,\"inviteeIds\":[2]}\n\n// after\n{\"conversationType\":1,\"peerUserId\":2}            // private\n// or\n{\"conversationType\":2,\"groupId\":10,\"inviteeIds\":[2,3]} // group","handlingStrategy":"type-guard","validationCode":"Integer ct = reqVO.getConversationType();\nif (!ImConversationTypeEnum.isPrivate(ct) && !ImConversationTypeEnum.isGroup(ct)) {\n    throw new IllegalArgumentException(\"conversationType 必须为 私聊 或 群聊\");\n}","typeGuard":"boolean isKnownConversationType(Integer ct) {\n    return ImConversationTypeEnum.isPrivate(ct) || ImConversationTypeEnum.isGroup(ct);\n}","tryCatchPattern":null,"preventionTips":["Send conversationType from a shared enum, never free-form","Make the field required in the request VO so absent values 400 early","For group calls, pre-check groupId + non-empty inviteeIds client-side"],"tags":["im","rtc","conversation-type","validation"],"backgroundTag":null,"analyzedSha":"477be9dd49ab7223a972a6abdff0684d6423dec3","analyzedAt":"2026-08-14T13:35:31.121Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}