flowable/flowable-engine · error · FlowableIllegalArgumentException

Type is required.

Error message

Type is required.

What it means

Flowable REST throws FlowableIllegalArgumentException when the identity link 'type' path segment is null while validating arguments in validateIdentityLinkArguments. The type (e.g. 'participant', 'starter') is mandatory to identify the specific identity link.

Solutions

  1. Append the identity link type to the URL, e.g. /identitylinks/users/{identityId}/participant.
  2. Check the identity link's type via the identity link collection endpoint before deleting.
  3. Ensure proxy/rewrite rules do not strip the trailing path segment.

Example fix

// before
delete("/runtime/process-instances/" + pid + "/identitylinks/users/" + userId);
// after
delete("/runtime/process-instances/" + pid + "/identitylinks/users/" + userId + "/participant");
Defensive patterns

Strategy: validation

Validate before calling

if (!linkType) throw new Error('identity link type required, e.g. participant');

Type guard

const hasType = (s) => typeof s === 'string' && s.length > 0;

Prevention

When it happens

Trigger: DELETE to /runtime/process-instances/{id}/identitylinks/users/{identityId}/ with an empty {type} segment; deleting a link without appending the type part of the URL.

Common situations: Client omits the third path segment when deleting an identity link; assumes type is optional because the REST docs list only family and identityId in some examples; wrong number of segments after URL rewriting.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/ea1c35c01361ddc9. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceIdentityLinkResource.java:106

        }

        if (RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family)) {
            runtimeService.deleteGroupIdentityLink(processInstance.getId(), identityId, type);
            
        } else {
            runtimeService.deleteUserIdentityLink(processInstance.getId(), identityId, type);
        }
    }

    protected void validateIdentityLinkArguments(String family, String identityId, String type) {
        if (family == null || (!RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family) && !RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family))) {
            throw new FlowableIllegalArgumentException("Identity link family should be 'users' or 'groups'.");
        }
        if (identityId == null) {
            throw new FlowableIllegalArgumentException("IdentityId is required.");
        }
        if (type == null) {
            throw new FlowableIllegalArgumentException("Type is required.");
        }
    }

    protected IdentityLink getIdentityLink(String identityId, String family, String type, String processInstanceId) {
        // Perhaps it would be better to offer getting a single identity link
        // from the API
        List<IdentityLink> allLinks = runtimeService.getIdentityLinksForProcessInstance(processInstanceId);
        for (IdentityLink link : allLinks) {
            if (RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family) && identityId.equals(link.getUserId()) && link.getType().equals(type)) {
                return link;
            
            } else if (RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family) && identityId.equals(link.getGroupId()) && link.getType().equals(type)) {
                return link;
            }
        }
        throw new FlowableObjectNotFoundException("Could not find the requested identity link.", IdentityLink.class);
    }
}

View on GitHub (pinned to d6d39ce1c6)