{"record":{"id":"cdbb5ce48db7b4ea","repo":"flowable/flowable-engine","slug":"task-is-already-claimed-by-someone-else","errorCode":null,"errorMessage":"Task '' is already claimed by someone else.","messagePattern":"Task '' is already claimed by someone else\\.","errorType":"exception","errorClass":"FlowableTaskAlreadyClaimedException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ClaimTaskCmd.java","lineNumber":60,"sourceCode":"    protected Void execute(CommandContext commandContext, TaskEntity task) {\n        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, task.getProcessDefinitionId())) {\n            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();\n            compatibilityHandler.claimTask(taskId, userId);\n            return null;\n        }\n\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\n        if (userId != null) {\n            Clock clock = processEngineConfiguration.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                CommandContextUtil.getActivityInstanceEntityManager(commandContext).recordTaskInfoChange(task, clock.getCurrentTime());\n                \n            } else {\n                TaskHelper.changeTaskAssignee(task, userId);\n                \n                if (processEngineConfiguration.getUserTaskStateInterceptor() != null) {\n                    processEngineConfiguration.getUserTaskStateInterceptor().handleClaim(task, userId);\n                }\n            }\n            \n            CommandContextUtil.getHistoryManager().createUserIdentityLinkComment(task, userId, IdentityLinkType.ASSIGNEE, true);\n            \n        } else {\n            if (task.getAssignee() != null) {\n                // Task claim time should be null\n                task.setClaimTime(null);\n                task.setClaimedBy(null);","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ClaimTaskCmd.java#L42-L78","documentation":"ClaimTaskCmd claims a task for a user. If the task already has an assignee different from the claiming user, Flowable throws FlowableTaskAlreadyClaimedException; claiming by the same assignee is silently ignored.","triggerScenarios":"taskService.claim(taskId, userId) where the task's current assignee is another user; two users claiming concurrently.","commonSituations":"Collaborative task lists where multiple users click 'claim' at once; retrying a claim after another user already took it; stale UI showing the task as unclaimed.","solutions":["Catch FlowableTaskAlreadyClaimedException and refresh the task state / notify the user.","Use taskService.createTaskQuery().taskId(id).taskAssignee(userId) beforehand to check current assignee.","Call taskService.unclaim(taskId) first if reassignment is intended (with appropriate authorization)."],"exampleFix":"// before\ntaskService.claim(taskId, userId);\n// after\ntry {\n    taskService.claim(taskId, userId);\n} catch (FlowableTaskAlreadyClaimedException e) {\n    // task already assigned to e.getCurrentAssignee(); refresh UI\n}","handlingStrategy":"try-catch","validationCode":"Task t = taskService.createTaskQuery().taskId(taskId).singleResult();\nboolean claimable = t != null && t.getAssignee() == null;","typeGuard":null,"tryCatchPattern":"try {\n    taskService.claim(taskId, userId);\n} catch (FlowableTaskAlreadyClaimedException e) {\n    // refresh UI, show current assignee e.getCurrentAssignee()\n}","preventionTips":["Always wrap claim in a handler for FlowableTaskAlreadyClaimedException.","Refresh task lists after claiming to avoid stale assignee info.","Check current assignee first when the UI allows a claim attempt."],"tags":["flowable","task","concurrency","claim"],"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"}