{"record":{"id":"06948a3ce062b091","repo":"flowable/flowable-engine","slug":"task-taskid-is-already-claimed-by-someone-els","errorCode":null,"errorMessage":"Task '${taskId}' is already claimed by someone else.","messagePattern":"Task '(.+?)' is already claimed by someone else\\.","errorType":"exception","errorClass":"ActivitiTaskAlreadyClaimedException","httpStatus":null,"severity":"warning","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/ClaimTaskCmd.java","lineNumber":41,"sourceCode":"\n    private static final long serialVersionUID = 1L;\n\n    protected String userId;\n\n    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\n        if (userId != null) {\n            if (task.getAssignee() != null) {\n                if (!task.getAssignee().equals(userId)) {\n                    // When the task is already claimed by another user, throw exception. Otherwise, ignore\n                    // this, post-conditions of method already met.\n                    throw new ActivitiTaskAlreadyClaimedException(task.getId(), task.getAssignee());\n                }\n            } else {\n                task.setAssignee(userId, true, true);\n            }\n        } else {\n            // Task should be assigned to no one\n            task.setAssignee(null, true, true);\n        }\n\n        // Add claim time\n        commandContext.getHistoryManager().recordTaskClaim(taskId);\n\n        return null;\n    }\n\n    @Override\n    protected String getSuspendedTaskException() {\n        return \"Cannot claim a suspended task\";","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/ClaimTaskCmd.java#L23-L59","documentation":"ActivitiTaskAlreadyClaimedException is thrown by ClaimTaskCmd when the task already has an assignee different from the user attempting to claim it. The engine enforces single-claim semantics: if the same user re-claims, it silently succeeds; another user gets this exception.","triggerScenarios":"taskService.claim(taskId, userId) where task.getAssignee() is a different, non-null user.","commonSituations":"Two agents in a tasklist UI claiming simultaneously; a stale UI screen showing the task as unassigned; automation racing a human claimer.","solutions":["Catch ActivitiTaskAlreadyClaimedException and refresh the task state in the UI","Check task.getAssignee() before claiming and handle the already-claimed case","Unclaim (setAssignee(taskId, null)) first if your workflow intentionally allows reassignment"],"exampleFix":"// before\ntaskService.claim(taskId, userId);\n// after\ntry {\n    taskService.claim(taskId, userId);\n} catch (ActivitiTaskAlreadyClaimedException e) {\n    String currentAssignee = taskService.createTaskQuery().taskId(taskId).singleResult().getAssignee();\n    // notify user the task is held by currentAssignee\n}","handlingStrategy":"try-catch","validationCode":"Task t = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (t != null && t.getAssignee() != null && !userId.equals(t.getAssignee())) { /* already claimed elsewhere */ }","typeGuard":"boolean claimable(Task t, String userId) { return t != null && (t.getAssignee() == null || t.getAssignee().equals(userId)); }","tryCatchPattern":"try { taskService.claim(taskId, userId); } catch (ActivitiTaskAlreadyClaimedException e) { /* refresh UI, show current assignee */ }","preventionTips":["Refresh task state before claiming in UIs","Treat claims as optimistic-lock style operations","Use task listeners/optimistic locking to resolve races"],"tags":["concurrency","task","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-18T11:17:12.947Z"}