flowable/flowable-engine · error · ActivitiIllegalArgumentException

type is required when deleting a process identity link

Error message

type is required when deleting a process identity link

What it means

DeleteIdentityLinkForProcessInstanceCmd requires an identity link type (e.g. "candidate", "participant") when deleting a process instance identity link; a null type is rejected with ActivitiIllegalArgumentException because the engine cannot determine which link kind to remove. It mirrors the IdentityLinkType constants used when links are added.

Solutions

  1. Pass the exact identity link type used when the link was added (IdentityLinkType constants like PARTICIPANT).
  2. If the type is unknown, query runtimeService.getIdentityLinksForProcessInstance(processInstanceId) and use the returned link's getType().
  3. Guard the type argument with a null check before the call.

Example fix

// before
runtimeService.deleteProcessInstanceIdentityLink(pid, userId, null, linkType); // linkType == null
// after
String linkType = link != null ? link.getType() : IdentityLinkType.PARTICIPANT;
runtimeService.deleteProcessInstanceIdentityLink(pid, userId, null, linkType);
Defensive patterns

Strategy: validation

Validate before calling

if (type == null) {
    throw new IllegalArgumentException("Identity link type is required (see IdentityLinkType constants)");
}

Type guard

boolean hasLinkType(String type) { return type != null && !type.trim().isEmpty(); }

Try / catch

try {
    runtimeService.deleteProcessInstanceIdentityLink(pid, userId, groupId, type);
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("type is required")) {
        throw new IllegalArgumentException("Supply the IdentityLinkType used when the link was added", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling runtimeService.deleteProcessInstanceIdentityLink(processInstanceId, userId, groupId, null) — user/group supplied but the type argument is null.

Common situations: The link was created programmatically without a recorded type; callers copy the addIdentityLink call but drop the type parameter; or a wrapper method defaults the type to null.

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/bb9980d9a6425287. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteIdentityLinkForProcessInstanceCmd.java:53

    protected String groupId;

    protected String type;

    public DeleteIdentityLinkForProcessInstanceCmd(String processInstanceId, String userId, String groupId, String type) {
        validateParams(userId, groupId, processInstanceId, type);
        this.processInstanceId = processInstanceId;
        this.userId = userId;
        this.groupId = groupId;
        this.type = type;
    }

    protected void validateParams(String userId, String groupId, String processInstanceId, String type) {
        if (processInstanceId == null) {
            throw new ActivitiIllegalArgumentException("processInstanceId is null");
        }

        if (type == null) {
            throw new ActivitiIllegalArgumentException("type is required when deleting a process identity link");
        }

        if (userId == null && groupId == null) {
            throw new ActivitiIllegalArgumentException("userId and groupId cannot both be null");
        }
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ExecutionEntity processInstance = commandContext.getExecutionEntityManager().findExecutionById(processInstanceId);

        if (processInstance == null) {
            throw new ActivitiObjectNotFoundException("Cannot find process instance with id " + processInstanceId, ExecutionEntity.class);
        }

        processInstance.deleteIdentityLink(userId, groupId, type);

        commandContext.getHistoryManager().createProcessInstanceIdentityLinkComment(processInstanceId, userId, groupId, type, false);

View on GitHub (pinned to d6d39ce1c6)