flowable/flowable-engine · error · FlowableForbiddenException
Cannot delete a task that is part of a case instance.
Error message
Cannot delete a task that is part of a case instance.
What it means
The Flowable CMMN REST API forbids deleting a standalone task via the REST endpoint when the task belongs to a running case instance. Task lifecycle in CMMN is owned by the case engine, so direct deletion would corrupt case state. The endpoint throws FlowableForbiddenException (HTTP 403) instead of performing the delete.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java:160
@ApiOperation(value = "Delete a task", tags = { "Tasks" }, code = 204)
@ApiImplicitParams({
@ApiImplicitParam(name = "cascadeHistory", dataType = "string", value = "Whether or not to delete the HistoricTask instance when deleting the task (if applicable). If not provided, this value defaults to false.", paramType = "query"),
@ApiImplicitParam(name = "deleteReason", dataType = "string", value = "Reason why the task is deleted. This value is ignored when cascadeHistory is true.", paramType = "query")
})
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the task was found and has been deleted. Response-body is intentionally empty."),
@ApiResponse(code = 403, message = "Indicates the requested task cannot be deleted because it’s part of a workflow."),
@ApiResponse(code = 404, message = "Indicates the requested task was not found.")
})
@DeleteMapping(value = "/cmmn-runtime/tasks/{taskId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteTask(@ApiParam(name = "taskId") @PathVariable String taskId, @ApiParam(hidden = true) @RequestParam(value = "cascadeHistory", required = false) Boolean cascadeHistory,
@ApiParam(hidden = true) @RequestParam(value = "deleteReason", required = false) String deleteReason) {
Task taskToDelete = getTaskFromRequestWithoutAccessCheck(taskId);
if (taskToDelete.getScopeId() != null && ScopeTypes.CMMN.equals(taskToDelete.getScopeType())) {
// Can't delete a task that is part of a case instance
throw new FlowableForbiddenException("Cannot delete a task that is part of a case instance.");
} else if (taskToDelete.getExecutionId() != null) {
throw new FlowableForbiddenException("Cannot delete a task that is part of a process instance.");
}
if (restApiInterceptor != null) {
restApiInterceptor.deleteTask(taskToDelete);
}
if (cascadeHistory != null) {
// Ignore delete-reason since the task-history (where the reason is
// recorded) will be deleted anyway
taskService.deleteTask(taskToDelete.getId(), cascadeHistory);
} else {
// Delete with delete-reason
taskService.deleteTask(taskToDelete.getId(), deleteReason);
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Complete, resolve, delegate, or terminate the task through the case engine instead of deleting it (POST /cmmn-runtime/tasks/{taskId} with action complete/terminate).
- Terminate the parent case instance, which removes its tasks, then clean up leftovers.
- If the task is truly orphaned, delete the case instance (DELETE /cmmn-runtime/case-instances/{caseInstanceId}) which cascades.
- Filter out tasks with scopeType=cmmn before issuing delete calls in batch jobs.
Example fix
// before
curl -X DELETE /flowable-rest/cmmn-runtime/tasks/123
// throws: Cannot delete a task that is part of a case instance.
// after
curl -X POST /flowable-rest/cmmn-runtime/tasks/123 -H 'Content-Type: application/json' -d '{"action":"complete"}' Defensive patterns
Strategy: try-catch
Validate before calling
const task = await api.get(`/cmmn-runtime/tasks/${id}`);
if (task.scopeType === 'cmmn' && task.scopeId) throw new Error('task belongs to a case instance; use case actions instead'); Type guard
function isCaseTask(t) { return !!t.scopeId && t.scopeType === 'cmmn'; } Try / catch
try { await api.delete(`/cmmn-runtime/tasks/${id}`); } catch (e) { if (e.response && e.response.status === 403) { /* complete or terminate the case task instead */ } else { throw e; } } Prevention
- Check scopeId/scopeType before deleting any task
- Use case-level terminate/complete operations for case-owned tasks
- Document that DELETE is only for standalone tasks
When it happens
Trigger: Calling DELETE /cmmn-runtime/tasks/{taskId} where the task has a non-null scopeId with scopeType 'cmmn' (i.e. it was created as part of a case instance).
Common situations: Admin cleanup scripts that delete stale tasks; deleting a task created by a human task / case task stage in a case definition; scripts written for standalone tasks reused against case tasks.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot delete a task that is part of a process instance.
- Cannot delete a task that is part of a case instance.
- Task ${taskId} is not suspended, so can't be activated
- is created by the process engine and should be completed vi
- The ${task} cannot be deleted because is part of a running c
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e5eea5f383d32100.
Report an issue: GitHub.