flowable/flowable-engine · error · FlowableIllegalArgumentException

The taskId or processDefinitionId property has to be…

Error message

The taskId or processDefinitionId property has to be provided

What it means

submitForm requires exactly one target: either a taskId (task form) or a processDefinitionId (start form). FlowableIllegalArgumentException is thrown when the parsed request body has neither property set, because there is nothing to submit the form for.

Solutions

  1. Include taskId to submit a task form, or processDefinitionId to submit a start form
  2. Validate the payload on the client before the POST
  3. Catch FlowableIllegalArgumentException (HTTP 400) and prompt the user for the missing identifier

Example fix

// before
{"formProperties":[{"id":"approved","value":"true"}]}

// after
{"taskId":"125","formProperties":[{"id":"approved","value":"true"}]}
Defensive patterns

Strategy: validation

Validate before calling

if (request.taskId == null && request.processDefinitionId == null) {
  throw new Error('taskId or processDefinitionId must be provided before submitForm');
}

Type guard

function hasSubmitTarget(r) { return r != null && (typeof r.taskId === 'string' || typeof r.processDefinitionId === 'string'); }

Try / catch

try { await submitForm(req); } catch (e) { if (e.status === 400 && /taskId or processDefinitionId/.test(e.message)) promptForTarget(); else throw e; }

Prevention

When it happens

Trigger: POST /form/form-data with a JSON body that omits both taskId and processDefinitionId, e.g. {"formProperties":[...]} only.

Common situations: Client builds the payload dynamically and the id field is dropped when null; copying an example payload without filling in the id; field-name typos like processDefinitionID.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/380e50d79597cf3d. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/form/FormDataResource.java:110

        }

        return restResponseFactory.createFormDataResponse(formData);
    }

    @ApiOperation(value = "Submit task form data", tags = { "Forms" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates request was successful and the form data was submitted"),
            @ApiResponse(code = 204, message = "If TaskId has been provided, Indicates request was successful and the form data was submitted. Returns empty"),
            @ApiResponse(code = 400, message = "Indicates an parameter was passed in the wrong format. The status-message contains additional information.") })
    @PostMapping(value = "/form/form-data", produces = "application/json")
    public ProcessInstanceResponse submitForm(@RequestBody SubmitFormRequest submitRequest, HttpServletResponse response) {

        if (submitRequest == null) {
            throw new FlowableException("A request body was expected when executing the form submit.");
        }

        if (submitRequest.getTaskId() == null && submitRequest.getProcessDefinitionId() == null) {
            throw new FlowableIllegalArgumentException("The taskId or processDefinitionId property has to be provided");
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.submitFormData(submitRequest);
        }

        Map<String, String> propertyMap = new HashMap<>();
        if (submitRequest.getProperties() != null) {
            for (RestFormProperty formProperty : submitRequest.getProperties()) {
                propertyMap.put(formProperty.getId(), formProperty.getValue());
            }
        }

        if (submitRequest.getTaskId() != null) {
            formService.submitTaskFormData(submitRequest.getTaskId(), propertyMap);
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return null;

View on GitHub (pinned to d6d39ce1c6)