{"record":{"id":"eae430ce7b3112fa","repo":"flowable/flowable-engine","slug":"incompatible-usage-cannot-use-type-type-toge","errorCode":null,"errorMessage":"Incompatible usage: cannot use type '${type}' together with a groupId","messagePattern":"Incompatible usage: cannot use type '(.+?)' together with a groupId","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteIdentityLinkCmd.java","lineNumber":65,"sourceCode":"        this.taskId = taskId;\n        this.userId = userId;\n        this.groupId = groupId;\n        this.type = type;\n    }\n\n    protected void validateParams(String userId, String groupId, String type, String taskId) {\n        if (taskId == null) {\n            throw new FlowableIllegalArgumentException(\"taskId is null\");\n        }\n\n        if (type == null) {\n            throw new FlowableIllegalArgumentException(\"type is required when adding a new task identity link\");\n        }\n\n        // Special treatment for assignee and owner: group cannot be used and userId may be null\n        if (IdentityLinkType.ASSIGNEE.equals(type) || IdentityLinkType.OWNER.equals(type)) {\n            if (groupId != null) {\n                throw new FlowableIllegalArgumentException(\"Incompatible usage: cannot use type '\" + type + \"' together with a groupId\");\n            }\n        } else {\n            if (userId == null && groupId == null) {\n                throw new FlowableIllegalArgumentException(\"userId and groupId cannot both be null\");\n            }\n        }\n    }\n\n    @Override\n    protected Void execute(CommandContext commandContext, TaskEntity task) {\n        if (task.getProcessDefinitionId() != null && Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, task.getProcessDefinitionId())) {\n            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();\n            compatibilityHandler.deleteIdentityLink(taskId, userId, groupId, type);\n            return null;\n        }\n\n        if (IdentityLinkType.ASSIGNEE.equals(type)) {\n            TaskHelper.changeTaskAssignee(task, null);","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteIdentityLinkCmd.java#L47-L83","documentation":"DeleteIdentityLinkCmd rejects semantically invalid combinations: ASSIGNEE and OWNER links apply to a single user, so a groupId is incompatible; for all other types, at least one of userId or groupId must be provided. Violations throw FlowableIllegalArgumentException.","triggerScenarios":"deleteUserIdentityLink/deleteGroupIdentityLink calls where type is ASSIGNEE or OWNER but a groupId is passed, or where both userId and groupId are null for any other type.","commonSituations":"Copy-paste between user and group link APIs, generic link-removal helpers that pass both userId/groupId through unchecked, or code computing type dynamically (assignee) while still supplying a group id.","solutions":["For ASSIGNEE/OWNER types pass only a userId and null groupId","For other types ensure exactly the relevant id (userId or groupId) is non-null","Split the removal logic into user-link and group-link branches instead of one generic call"],"exampleFix":"// before\ntaskService.deleteGroupIdentityLink(taskId, groupId, IdentityLinkType.ASSIGNEE); // incompatible\n// after\ntaskService.deleteUserIdentityLink(taskId, userId, IdentityLinkType.ASSIGNEE);","handlingStrategy":"validation","validationCode":"boolean valid;\nif (IdentityLinkType.ASSIGNEE.equals(type) || IdentityLinkType.OWNER.equals(type)) {\n    valid = groupId == null;\n} else {\n    valid = userId != null || groupId != null;\n}\nif (!valid) {\n    throw new IllegalArgumentException(\"Invalid identity link argument combination for type \" + type);\n}","typeGuard":"boolean isValidLinkCombo = (type, userId, groupId) ->\n    (IdentityLinkType.ASSIGNEE.equals(type) || IdentityLinkType.OWNER.equals(type))\n        ? groupId == null\n        : userId != null || groupId != null;","tryCatchPattern":"try {\n    taskService.deleteGroupIdentityLink(taskId, groupId, type);\n} catch (FlowableIllegalArgumentException e) {\n    logger.warn(\"Incompatible identity link arguments\", e);\n}","preventionTips":["For ASSIGNEE/OWNER always use userId-only APIs","Keep user-link and group-link removal in separate code paths","Mirror the engine's validateParams rules in your own helper layer"],"tags":["flowable","invalid-argument","identity-link","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T16:30:33.424Z"}