flowable/flowable-engine · error · FlowableTaskAlreadyClaimedException
Task '
Error message
Task '
What it means
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.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ClaimTaskCmd.java:51
public ClaimTaskCmd(String taskId, String userId) {
super(taskId);
this.userId = userId;
}
@Override
protected Void execute(CommandContext commandContext, TaskEntity task) {
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
if (userId != null) {
Clock clock = cmmnEngineConfiguration.getClock();
task.setClaimTime(clock.getCurrentTime());
task.setClaimedBy(userId);
task.setState(Task.CLAIMED);
if (task.getAssignee() != null) {
if (!task.getAssignee().equals(userId)) {
// When the task is already claimed by another user, throw
// exception. Otherwise, ignore this, post-conditions of method already met.
throw new FlowableTaskAlreadyClaimedException(task.getId(), task.getAssignee());
}
cmmnEngineConfiguration.getCmmnHistoryManager().recordTaskInfoChange(task, clock.getCurrentTime());
} else {
TaskHelper.changeTaskAssignee(task, userId, cmmnEngineConfiguration);
if (cmmnEngineConfiguration.getHumanTaskStateInterceptor() != null) {
cmmnEngineConfiguration.getHumanTaskStateInterceptor().handleClaim(task, userId);
}
}
} else {
if (task.getAssignee() != null) {
// Task claim time should be null
task.setClaimTime(null);
task.setClaimedBy(null);
if (task.getInProgressStartTime() != null) {View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
// before
cmmnTaskService.claim(taskId, userId);
// after
try {
cmmnTaskService.claim(taskId, userId);
} catch (FlowableTaskAlreadyClaimedException e) {
logger.info("Task " + taskId + " already claimed by another user");
} Defensive patterns
Strategy: try-catch
Validate before calling
Task t = cmmnTaskService.createTaskQuery().taskId(taskId).singleResult();
boolean claimable = t != null && t.getAssignee() == null;
if (!claimable) { /* skip or notify */ } Try / catch
try { cmmnTaskService.claim(taskId, userId); } catch (FlowableTaskAlreadyClaimedException e) { notifyAlreadyClaimed(e.getTaskId(), e.getAssignee()); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Null task id
- Task '' is already claimed by someone else.
- Setting transient variable is not supported for read only de
- Setting localized name is not supported for read only delega
- Could not find an implementation of the org.flowable.cdi.imp
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ac16df448f1eda29.
Report an issue: GitHub.