{"record":{"id":"946c9215dab1316d","repo":"flowable/flowable-engine","slug":"an-assignee-is-required-when-delegating-a-task","errorCode":null,"errorMessage":"An assignee is required when delegating a task.","messagePattern":"An assignee is required when delegating a task\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java","lineNumber":247,"sourceCode":"                    taskCompletionBuilder.transientVariable(var.getName(), actualVariableValue);\n                }\n            }\n        }\n\n        taskCompletionBuilder\n                .taskId(task.getId())\n                .formDefinitionId(actionRequest.getFormDefinitionId())\n                .outcome(actionRequest.getOutcome())\n                .complete();\n    }\n\n    protected void resolveTask(Task task, TaskActionRequest actionRequest) {\n        taskService.resolveTask(task.getId());\n    }\n\n    protected void delegateTask(Task task, TaskActionRequest actionRequest) {\n        if (actionRequest.getAssignee() == null) {\n            throw new FlowableIllegalArgumentException(\"An assignee is required when delegating a task.\");\n        }\n        taskService.delegateTask(task.getId(), actionRequest.getAssignee());\n    }\n\n    protected void claimTask(Task task, TaskActionRequest actionRequest) {\n        // In case the task is already claimed, a\n        // FlowableTaskAlreadyClaimedException is thrown and converted to\n        // a CONFLICT response by the ExceptionHandlerAdvice\n        taskService.claim(task.getId(), actionRequest.getAssignee());\n    }\n\n    protected void unclaimTask(Task task) {\n        taskService.unclaim(task.getId());\n    }\n}\n","sourceCodeStart":229,"sourceCodeEnd":263,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java#L229-L263","documentation":"Delegating a task requires a target assignee; the delegate action reads 'assignee' from the action request and throws FlowableIllegalArgumentException (HTTP 400) when it is null. Delegation without a receiver is meaningless to the engine.","triggerScenarios":"POST /cmmn-runtime/tasks/{taskId} with action 'delegate' but no assignee field in the request body.","commonSituations":"UI forms that allow submitting delegate without selecting a user; copy-pasted claim/complete payloads lacking assignee; client code path where assignee resolution returned null.","solutions":["Include \"assignee\":\"<userId>\" in the action request body.","Validate the assignee field in the client before dispatching the delegate action.","If no assignee exists, use action 'claim' or 'complete' instead of delegate.","Resolve a fallback assignee (e.g. group lead) when the selected user is null."],"exampleFix":"// before\n{\"action\":\"delegate\"}\n\n// after\n{\"action\":\"delegate\",\"assignee\":\"kermit\"}","handlingStrategy":"validation","validationCode":"if (!body.assignee) throw new Error('assignee is required for the delegate action');","typeGuard":"const canDelegate = (req) => typeof req.assignee === 'string' && req.assignee.length > 0;","tryCatchPattern":"try { await api.post(`/cmmn-runtime/tasks/${id}`, {action:'delegate', assignee}); } catch (e) { if (e.response && e.response.status === 400) { /* prompt for an assignee */ } throw e; }","preventionTips":["Require assignee selection in the UI before allowing delegate","Default to a fallback assignee when none is chosen","Validate action-specific required fields in a shared request builder"],"tags":["rest-api","cmmn","validation","delegation"],"backgroundTag":"missing-required-argument","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"}