{"record":{"id":"891500c2616b87dc","repo":"flowable/flowable-engine","slug":"identityid-is-required-891500","errorCode":null,"errorMessage":"IdentityId is required.","messagePattern":"IdentityId is required\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskIdentityLinkResource.java","lineNumber":100,"sourceCode":"        IdentityLink link = getIdentityLink(family, identityId, type, task.getId());\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.deleteTaskIdentityLink(task, link);\n        }\n\n        if (CmmnRestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family)) {\n            taskService.deleteUserIdentityLink(task.getId(), identityId, type);\n        } else {\n            taskService.deleteGroupIdentityLink(task.getId(), identityId, type);\n        }\n    }\n\n    protected void validateIdentityLinkArguments(String family, String identityId, String type) {\n        if (family == null || (!CmmnRestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family) && !CmmnRestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family))) {\n            throw new FlowableIllegalArgumentException(\"Identity link family should be 'users' or 'groups'.\");\n        }\n        if (identityId == null) {\n            throw new FlowableIllegalArgumentException(\"IdentityId is required.\");\n        }\n        if (type == null) {\n            throw new FlowableIllegalArgumentException(\"Type is required.\");\n        }\n    }\n\n    protected IdentityLink getIdentityLink(String family, String identityId, String type, String taskId) {\n        boolean isUser = family.equals(CmmnRestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS);\n\n        // Perhaps it would be better to offer getting a single identitylink\n        // from the API\n        List<IdentityLink> allLinks = taskService.getIdentityLinksForTask(taskId);\n        for (IdentityLink link : allLinks) {\n            boolean rightIdentity = false;\n            if (isUser) {\n                rightIdentity = identityId.equals(link.getUserId());\n            } else {\n                rightIdentity = identityId.equals(link.getGroupId());","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskIdentityLinkResource.java#L82-L118","documentation":"Deleting or fetching a single identity link requires the identityId path variable (the user or group name). If it is absent or null, validateIdentityLinkArguments throws FlowableIllegalArgumentException because a link cannot be uniquely addressed without it.","triggerScenarios":"GET/DELETE /cmmn-runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type} with an empty or missing {identityId} segment.","commonSituations":"A user/group name that was never populated in the calling code; empty string from a config field; URL templating that drops empty path variables.","solutions":["Provide the actual user or group id in the URL path","Check that the variable holding the identity name is non-null/non-empty before building the URL","Fail fast in client code when the principal name is unknown instead of issuing the call"],"exampleFix":"// before\nString url = \"/cmmn-runtime/tasks/123/identitylinks/users/\" + userId + \"/candidate\"; // userId == null\n// after\nObjects.requireNonNull(userId, \"userId required for identity link lookup\");\nString url = \"/cmmn-runtime/tasks/123/identitylinks/users/\" + userId + \"/candidate\";","handlingStrategy":"validation","validationCode":"function canAddressIdentityLink(family, identityId, type) {\n  return !!identityId && !!type && ['users','groups'].includes(family);\n}","typeGuard":"function hasIdentityId(a) {\n  return typeof a.identityId === 'string' && a.identityId.length > 0;\n}","tryCatchPattern":"try {\n  await del(url);\n} catch (e) {\n  if (e.status === 400 && /IdentityId is required/.test(e.body.message)) {\n    throw new Error('identityId path variable missing');\n  }\n  throw e;\n}","preventionTips":["Guard identityId before constructing the URL","Fail fast when the principal name is unknown rather than issuing a doomed call","Check for empty strings, not just null/undefined"],"tags":["rest-api","missing-parameter","identity-link"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}