{"record":{"id":"18d6d4f0cb2287fc","repo":"flowable/flowable-engine","slug":"a-request-body-was-expected-when-executing-the-for","errorCode":null,"errorMessage":"A request body was expected when executing the form submit.","messagePattern":"A request body was expected when executing the form submit\\.","errorType":"exception","errorClass":"FlowableException","httpStatus":500,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/form/FormDataResource.java","lineNumber":106,"sourceCode":"        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessFormData(formData);\n        }\n\n        return restResponseFactory.createFormDataResponse(formData);\n    }\n\n    @ApiOperation(value = \"Submit task form data\", tags = { \"Forms\" })\n    @ApiResponses(value = {\n            @ApiResponse(code = 200, message = \"Indicates request was successful and the form data was submitted\"),\n            @ApiResponse(code = 204, message = \"If TaskId has been provided, Indicates request was successful and the form data was submitted. Returns empty\"),\n            @ApiResponse(code = 400, message = \"Indicates an parameter was passed in the wrong format. The status-message contains additional information.\") })\n    @PostMapping(value = \"/form/form-data\", produces = \"application/json\")\n    public ProcessInstanceResponse submitForm(@RequestBody SubmitFormRequest submitRequest, HttpServletResponse response) {\n\n        if (submitRequest == null) {\n            throw new FlowableException(\"A request body was expected when executing the form submit.\");\n        }\n\n        if (submitRequest.getTaskId() == null && submitRequest.getProcessDefinitionId() == null) {\n            throw new FlowableIllegalArgumentException(\"The taskId or processDefinitionId property has to be provided\");\n        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.submitFormData(submitRequest);\n        }\n\n        Map<String, String> propertyMap = new HashMap<>();\n        if (submitRequest.getProperties() != null) {\n            for (RestFormProperty formProperty : submitRequest.getProperties()) {\n                propertyMap.put(formProperty.getId(), formProperty.getValue());\n            }\n        }\n\n        if (submitRequest.getTaskId() != null) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/form/FormDataResource.java#L88-L124","documentation":"submitForm is declared with @RequestBody, so Spring would normally reject empty bodies, but Flowable guards explicitly: if the deserialized SubmitFormRequest is null (e.g. body was empty/whitespace or Content-Type mismatch prevented binding), it throws FlowableException with this message. It protects downstream code from dereferencing a null request object.","triggerScenarios":"POST /form/form-data with an empty body, a body that is literally 'null', or a request whose Content-Type is not application/json so no body is bound.","commonSituations":"HTTP clients omitting -d/--data in curl; wrong Content-Type header (text/plain or form-urlencoded); proxies stripping the body on POST.","solutions":["Send a valid JSON body with Content-Type: application/json","Ensure the body contains at least taskId or processDefinitionId plus form properties","Catch FlowableException mapped to HTTP 400 and validate the client payload before sending"],"exampleFix":"// before\ncurl -X POST -H \"Content-Type: application/json\" http://localhost:8080/flowable-rest/form/form-data\n\n// after\ncurl -X POST -H \"Content-Type: application/json\" \\\n  -d '{\"taskId\":\"125\",\"formProperties\":[{\"id\":\"approved\",\"value\":\"true\"}]}' \\\n  http://localhost:8080/flowable-rest/form/form-data","handlingStrategy":"validation","validationCode":"if (!body || typeof body !== 'object') throw new Error('submitForm requires a JSON body');\nif (!body.taskId && !body.processDefinitionId) throw new Error('taskId or processDefinitionId required');","typeGuard":"function isSubmitFormRequest(v) { return v !== null && typeof v === 'object' && ('taskId' in v || 'processDefinitionId' in v); }","tryCatchPattern":"try { await submitForm(payload); } catch (e) { if (e.status === 400) showPayloadError(e); else throw e; }","preventionTips":["Always set Content-Type: application/json on POSTs","Serialize the payload explicitly; never send an empty body","Test endpoints with the exact client HTTP stack, including proxies"],"tags":["rest-api","flowable","request-body","validation"],"backgroundTag":"empty-required-field","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"}