flowable/flowable-engine · error · FlowableIllegalArgumentException

Either set the user id or the group id for an identity link,

Error message

Either set the user id or the group id for an identity link, but not both the same time.

What it means

A case instance identity link command was given both a userId and a groupId. Flowable identity links attach to exactly one principal, so both being set is rejected up front with FlowableIllegalArgumentException.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/AbstractCaseInstanceIdentityLinkCmd.java:78

    /**
     * Creates a new identity link entry for the given case instance, which can either be a user or group based one, but not both the same time.
     * If both the user and group ids are null, no new identity link is created.
     *
     * @param commandContext the command context within which to perform the identity link creation
     * @param caseInstanceId the id of the case instance to create an identity link for
     * @param userId the user id if this is a user based identity link, otherwise null
     * @param groupId the group id if this is a group based identity link, otherwise null
     * @param identityType the type of identity link (e.g. owner or assignee, etc)
     */
    protected void createIdentityLinkType(CommandContext commandContext, String caseInstanceId, String userId, String groupId, String identityType) {
        // if both user and group ids are null, don't create an identity link
        if (userId == null && groupId == null) {
            return;
        }

        // if both are set the same time, throw an exception as this is not allowed
        if (userId != null && groupId != null) {
            throw new FlowableIllegalArgumentException("Either set the user id or the group id for an identity link, but not both the same time.");
        }

        CaseInstanceEntity caseInstanceEntity = getCaseInstanceEntity(commandContext, caseInstanceId);
        IdentityLinkUtil.createCaseInstanceIdentityLink(caseInstanceEntity, userId, groupId, identityType,
            CommandContextUtil.getCmmnEngineConfiguration(commandContext));
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Validate input so exactly one of userId/groupId is set before calling the identity link API
  2. Call the API twice — once with userId, once with groupId — if both principals genuinely need the link
  3. Null out the unused field in your service layer before issuing the command

Example fix

// before
cmmnRuntimeService.addIdentityLink(caseInstanceId, userId, groupId, "participant"); // both set
// after
if (userId != null) {
    cmmnRuntimeService.addUserIdentityLink(caseInstanceId, userId, "participant");
} else if (groupId != null) {
    cmmnRuntimeService.addGroupIdentityLink(caseInstanceId, groupId, "participant");
}
Defensive patterns

Strategy: validation

Validate before calling

if (userId != null && groupId != null) throw new Error('provide either userId or groupId, not both');

Type guard

function exactlyOnePrincipal(userId, groupId) { return (userId == null) !== (groupId == null); }

Try / catch

try { addIdentityLink(...); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().startsWith('Either set the user id')) sanitizeInput(); else throw e; }

Prevention

When it happens

Trigger: createIdentityLinkType invoked with non-null userId AND non-null groupId, e.g. programmatically passing both when constructing the command via CaseService identity link APIs.

Common situations: Variables or config where user and group both populated; merging code paths that set defaults for both; form input that captures both fields without validation.

Related errors


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