{"record":{"id":"ac16df448f1eda29","repo":"flowable/flowable-engine","slug":"task","errorCode":null,"errorMessage":"Task '","messagePattern":"Task '","errorType":"exception","errorClass":"FlowableTaskAlreadyClaimedException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ClaimTaskCmd.java","lineNumber":51,"sourceCode":"    public ClaimTaskCmd(String taskId, String userId) {\n        super(taskId);\n        this.userId = userId;\n    }\n\n    @Override\n    protected Void execute(CommandContext commandContext, TaskEntity task) {\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        if (userId != null) {\n            Clock clock = cmmnEngineConfiguration.getClock();\n            task.setClaimTime(clock.getCurrentTime());\n            task.setClaimedBy(userId);\n            task.setState(Task.CLAIMED);\n\n            if (task.getAssignee() != null) {\n                if (!task.getAssignee().equals(userId)) {\n                    // When the task is already claimed by another user, throw\n                    // exception. Otherwise, ignore this, post-conditions of method already met.\n                    throw new FlowableTaskAlreadyClaimedException(task.getId(), task.getAssignee());\n                }\n                cmmnEngineConfiguration.getCmmnHistoryManager().recordTaskInfoChange(task, clock.getCurrentTime());\n                \n            } else {\n                TaskHelper.changeTaskAssignee(task, userId, cmmnEngineConfiguration);\n                \n                if (cmmnEngineConfiguration.getHumanTaskStateInterceptor() != null) {\n                    cmmnEngineConfiguration.getHumanTaskStateInterceptor().handleClaim(task, userId);\n                }\n            }\n            \n        } else {\n            if (task.getAssignee() != null) {\n                // Task claim time should be null\n                task.setClaimTime(null);\n                task.setClaimedBy(null);\n                \n                if (task.getInProgressStartTime() != null) {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ClaimTaskCmd.java#L33-L69","documentation":"While claiming a task, ClaimTaskCmd detects the task already has an assignee different from the claiming user and throws FlowableTaskAlreadyClaimedException (message begins with \"Task '\"). This enforces single-owner semantics: only the current assignee may re-claim (which is a no-op) and others are rejected.","triggerScenarios":"Calling cmmnTaskService.claim(taskId, userId) on a task whose task.getAssignee() is non-null and != userId, i.e. a second user claiming an already-claimed CMMN standalone task.","commonSituations":"Two agents/users clicking \"claim\" concurrently; retrying a claim from a different service account after the first succeeded; UI state that did not refresh assignee status.","solutions":["Catch FlowableTaskAlreadyClaimedException and treat it as \"already claimed by someone else\" in the UI/business flow.","Check the assignee first: Task task = cmmnTaskService.createTaskQuery().taskId(id).singleResult(); skip claim if task.getAssignee() != null.","If the previous claim is stale, have the current assignee unclaim (setAssignee(null)) or an admin reassign before claiming.","If the same user should be idempotently allowed, note that claiming with the same userId is silently ignored — only differing users throw."],"exampleFix":"// before\ncmmnTaskService.claim(taskId, userId);\n\n// after\ntry {\n    cmmnTaskService.claim(taskId, userId);\n} catch (FlowableTaskAlreadyClaimedException e) {\n    logger.info(\"Task \" + taskId + \" already claimed by another user\");\n}","handlingStrategy":"try-catch","validationCode":"Task t = cmmnTaskService.createTaskQuery().taskId(taskId).singleResult();\nboolean claimable = t != null && t.getAssignee() == null;\nif (!claimable) { /* skip or notify */ }","typeGuard":null,"tryCatchPattern":"try { cmmnTaskService.claim(taskId, userId); } catch (FlowableTaskAlreadyClaimedException e) { notifyAlreadyClaimed(e.getTaskId(), e.getAssignee()); }","preventionTips":["Query the assignee before claiming; treat claim as an optimistic operation.","Refresh UI state after successful claims to prevent duplicate claim attempts.","Use reassignment APIs for legitimate ownership transfers instead of raw claim."],"tags":["cmmn","task","claim","concurrency","java"],"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"}