{"record":{"id":"2c1b04e51111f82d","repo":"flowable/flowable-engine","slug":"case-instance","errorCode":null,"errorMessage":"Case instance '","messagePattern":"Case instance '","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"warning","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CaseInstanceClaimCmd.java","lineNumber":63,"sourceCode":"        this.caseInstanceId = caseInstanceId;\n        this.userId = userId;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        CaseInstanceEntityManager caseInstanceEntityManager = CommandContextUtil.getCaseInstanceEntityManager(commandContext);\n        CaseInstanceEntity caseInstanceEntity = caseInstanceEntityManager.findById(caseInstanceId);\n        if (caseInstanceEntity == null) {\n            throw new FlowableObjectNotFoundException(\"No case instance found for id = '\" + caseInstanceId + \"'.\", CaseInstance.class);\n        }\n\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        if (userId != null) {\n            List<IdentityLinkEntity> identityLinks = cmmnEngineConfiguration.getIdentityLinkServiceConfiguration()\n                    .getIdentityLinkService().findIdentityLinksByScopeIdAndType(caseInstanceId, ScopeTypes.CMMN);\n            for (IdentityLinkEntity identityLink : identityLinks) {\n                if (IdentityLinkType.ASSIGNEE.equals(identityLink.getType())) {\n                    throw new FlowableException(\"Case instance '\" + caseInstanceId + \"' is already claimed.\");\n                }\n            }\n\n            IdentityLinkUtil.createCaseInstanceIdentityLink(caseInstanceEntity, userId, null, IdentityLinkType.ASSIGNEE, cmmnEngineConfiguration);\n\n            caseInstanceEntityManager.updateCaseInstanceClaimTime(caseInstanceEntity, cmmnEngineConfiguration.getClock().getCurrentTime(), userId);\n\n            if (cmmnEngineConfiguration.getCaseInstanceStateInterceptor() != null) {\n                cmmnEngineConfiguration.getCaseInstanceStateInterceptor().handleClaim(caseInstanceEntity, userId);\n            }\n\n        } else {\n            IdentityLinkUtil.deleteCaseInstanceIdentityLinks(caseInstanceEntity, null, null, IdentityLinkType.ASSIGNEE, cmmnEngineConfiguration);\n\n            caseInstanceEntityManager.updateCaseInstanceClaimTime(caseInstanceEntity, null, null);\n\n            if (cmmnEngineConfiguration.getCaseInstanceStateInterceptor() != null) {\n                cmmnEngineConfiguration.getCaseInstanceStateInterceptor().handleUnclaim(caseInstanceEntity, userId);","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CaseInstanceClaimCmd.java#L45-L81","documentation":"Flowable CMMN throws this when calling CaseInstanceClaimCmd.execute for a case instance that already has an ASSIGNEE identity link, i.e. it has already been claimed by a user. Claiming is a one-time operation; re-claiming without unclaiming first is rejected to protect the existing assignee.","triggerScenarios":"Calling CmmnTaskService/cmmnEngine CaseInstanceService.claim(caseInstanceId, userId) on a case instance where findIdentityLinksByScopeIdAndType returns an identity link of type ASSIGNEE.","commonSituations":"Two users clicking a 'claim' button concurrently; a retry of a claim request after it already succeeded; UI not refreshing claim state after another user claimed; batch job reprocessing the same case instance.","solutions":["Check whether the case instance is already claimed before calling claim, e.g. via identityLinkService.findIdentityLinksByScopeIdAndType(caseInstanceId, ScopeTypes.CMMN) and looking for an ASSIGNEE link","Catch FlowableException and treat the 'is already claimed' message as an expected business condition, informing the user who holds the claim","If reassignment is intended, unclaim the case instance (remove assignee identity link) before claiming with the new user","Fix duplicate claim submission in the UI by disabling the claim action once a claim succeeds"],"exampleFix":"// before\ncaseInstanceService.claim(caseInstanceId, userId); // throws if already claimed\n// after\nList<IdentityLink> links = identityLinkService.findIdentityLinksByScopeIdAndType(caseInstanceId, ScopeTypes.CMMN);\nboolean claimed = links.stream().anyMatch(l -> IdentityLinkType.ASSIGNEE.equals(l.getType()));\nif (!claimed) {\n    caseInstanceService.claim(caseInstanceId, userId);\n}","handlingStrategy":"try-catch","validationCode":"boolean alreadyClaimed = cmmnEngineConfig.getIdentityLinkServiceConfiguration().getIdentityLinkService()\n    .findIdentityLinksByScopeIdAndType(caseInstanceId, ScopeTypes.CMMN).stream()\n    .anyMatch(l -> IdentityLinkType.ASSIGNEE.equals(l.getType()));\nif (alreadyClaimed) { /* skip claim or show holder */ }","typeGuard":null,"tryCatchPattern":"try {\n    caseInstanceService.claim(caseInstanceId, userId);\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"is already claimed\")) {\n        // surface friendly message to user\n    } else {\n        throw e;\n    }\n}","preventionTips":["Query identity links for an existing ASSIGNEE before claiming","Disable claim buttons once a claim succeeds and refresh case state","Handle retry/idempotency in workflows that re-submit claims"],"tags":["cmmn","claim","conflict","state-validation"],"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-18T11:17:12.947Z"}