{"record":{"id":"df2bedd914a56651","repo":"flowable/flowable-engine","slug":"process-instance-processinstanceid-is-al","errorCode":null,"errorMessage":"Process instance '\" + processInstanceId + \"' is already claimed.\"","messagePattern":"Process instance '\" \\+ processInstanceId \\+ \"' is already claimed\\.\"","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ProcessInstanceClaimCmd.java","lineNumber":70,"sourceCode":"    @Override\n    public Void execute(CommandContext commandContext) {\n        ExecutionEntityManager executionManager = CommandContextUtil.getExecutionEntityManager(commandContext);\n        ExecutionEntity processInstance = executionManager.findById(processInstanceId);\n        if (processInstance == null) {\n            throw new FlowableObjectNotFoundException(\"No process instance found for id = '\" + processInstanceId + \"'.\", ProcessInstance.class);\n\n        } else if (!processInstance.isProcessInstanceType()) {\n            throw new FlowableIllegalArgumentException(\"A process instance id is required, but the provided id \" + \"'\" + processInstanceId + \"' \" + \"points to a child execution of process instance \" + \"'\"\n                    + processInstance.getProcessInstanceId() + \"'. \" + \"Please invoke the \" + getClass().getSimpleName() + \" with a root execution id.\");\n        }\n\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\n        if (userId != null) {\n            List<IdentityLinkEntity> identityLinks = processEngineConfiguration.getIdentityLinkServiceConfiguration()\n                    .getIdentityLinkService().findIdentityLinksByProcessInstanceId(processInstanceId);\n            for (IdentityLinkEntity identityLink : identityLinks) {\n                if (IdentityLinkType.ASSIGNEE.equals(identityLink.getType())) {\n                    throw new FlowableException(\"Process instance '\" + processInstanceId + \"' is already claimed.\");\n                }\n            }\n\n            IdentityLinkUtil.createProcessInstanceIdentityLink(processInstance, userId, null, IdentityLinkType.ASSIGNEE);\n\n            executionManager.updateProcessInstanceClaimTime(processInstance,\n                    processEngineConfiguration.getClock().getCurrentTime(), userId);\n\n            if (processEngineConfiguration.getProcessInstanceStateInterceptor() != null) {\n                processEngineConfiguration.getProcessInstanceStateInterceptor().handleClaim(processInstance, userId);\n            }\n\n        } else {\n            IdentityLinkUtil.deleteProcessInstanceIdentityLinks(processInstance, null, null, IdentityLinkType.ASSIGNEE);\n\n            executionManager.updateProcessInstanceClaimTime(processInstance, null, null);\n\n            if (processEngineConfiguration.getProcessInstanceStateInterceptor() != null) {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ProcessInstanceClaimCmd.java#L52-L88","documentation":"Flowable throws this from ProcessInstanceClaimCmd.execute() when a user attempts to claim a process instance that already has an ASSIGNEE identity link. Claiming is exclusive: only one assignee can own a process instance at a time, so the command first loads all identity links for the instance and rejects the claim if an ASSIGNEE link already exists.","triggerScenarios":"Calling managementService.claimProcessInstance(processInstanceId, userId) (via ProcessInstanceClaimCmd) while another user is already recorded as ASSIGNEE for that process instance.","commonSituations":"Two agents racing to claim the same customer case from a work queue; a stale UI that does not refresh claim state; re-claiming an instance after a previous claim was never released.","solutions":["Check existing claim state before claiming: query identity links via IdentityLinkService.findIdentityLinksByProcessInstanceId and skip or route to the current assignee.","Release/unclaim the existing assignee first (delete the ASSIGNEE identity link) then re-claim with the new user.","Catch FlowableException in the claim path and treat it as a concurrency signal (reload state, notify caller the instance is taken).","Use optimistic UI refresh / retry with backoff when multiple users claim concurrently."],"exampleFix":"// before\nmanagementService.claimProcessInstance(processInstanceId, userId);\n// after\nList<IdentityLink> links = managementService.getIdentityLinkService()\n    .findIdentityLinksByProcessInstanceId(processInstanceId);\nboolean claimed = links.stream()\n    .anyMatch(l -> IdentityLinkType.ASSIGNEE.equals(l.getType()));\nif (!claimed) {\n    managementService.claimProcessInstance(processInstanceId, userId);\n} else {\n    // instance already claimed by another user - handle business case\n}","handlingStrategy":"try-catch","validationCode":"boolean isClaimed(String processInstanceId) {\n    return runtimeService.createProcessInstanceQuery()\n        .processInstanceId(processInstanceId)\n        .variableValueEquals(\"claimState\", \"claimed\")\n        .count() > 0; // or inspect identity links via IdentityLinkService\n}","typeGuard":null,"tryCatchPattern":"try {\n    managementService.claimProcessInstance(processInstanceId, userId);\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"is already claimed\")) {\n        // reload state, notify user instance is taken by another assignee\n    } else {\n        throw e;\n    }\n}","preventionTips":["Query identity links for an existing ASSIGNEE before claiming","Release the previous claim before re-assigning","Serialize claims per instance (queue/lock) in high-concurrency UIs","Refresh claim state in the UI before submit"],"tags":["flowable","concurrency","process-instance","claim-conflict"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}