{"record":{"id":"51cb87b363b142ed","repo":"flowable/flowable-engine","slug":"no-action-found-in-request-body-51cb87","errorCode":null,"errorMessage":"No action found in request body.","messagePattern":"No action found in request body\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionResource.java","lineNumber":99,"sourceCode":"        return restResponseFactory.createProcessDefinitionResponse(processDefinition);\n    }\n\n    // FIXME Unique endpoint but with multiple actions\n    @ApiOperation(value = \"Execute actions for a process definition\", tags = { \"Process Definitions\" },\n            notes = \"Execute actions for a process definition (Update category, Suspend or Activate)\")\n    @ApiResponses(value = {\n            @ApiResponse(code = 200, message = \"Indicates action has been executed for the specified process. (category altered, activate or suspend)\"),\n            @ApiResponse(code = 400, message = \"Indicates no category was defined in the request body.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested process definition was not found.\"),\n            @ApiResponse(code = 409, message = \"Indicates the requested process definition is already suspended or active.\")\n    })\n    @PutMapping(value = \"/repository/process-definitions/{processDefinitionId}\", produces = \"application/json\")\n    public ProcessDefinitionResponse executeProcessDefinitionAction(\n            @ApiParam(name = \"processDefinitionId\") @PathVariable String processDefinitionId,\n            @ApiParam(required = true) @RequestBody ProcessDefinitionActionRequest actionRequest) {\n\n        if (actionRequest == null) {\n            throw new FlowableIllegalArgumentException(\"No action found in request body.\");\n        }\n\n        ProcessDefinition processDefinition = getProcessDefinitionFromRequestWithoutAccessCheck(processDefinitionId);\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.executeProcessDefinitionAction(processDefinition, actionRequest);\n        }\n\n        if (actionRequest.getCategory() != null) {\n            // Update of category required\n            repositoryService.setProcessDefinitionCategory(processDefinition.getId(), actionRequest.getCategory());\n\n            // No need to re-fetch the ProcessDefinition entity, just update\n            // category in response\n            ProcessDefinitionResponse response = restResponseFactory.createProcessDefinitionResponse(processDefinition);\n            response.setCategory(actionRequest.getCategory());\n            return response;\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionResource.java#L81-L117","documentation":"executeProcessDefinitionAction (PUT on a process definition) requires a JSON body carrying an 'action' field. When the deserialized ProcessDefinitionActionRequest is null — i.e. no usable body was sent — Flowable rejects the request with this IllegalArgumentException.","triggerScenarios":"PUT /repository/process-definitions/{id} with an empty body, no Content-Type: application/json, or a body that deserializes to null.","commonSituations":"Testing with curl -X PUT without -d; clients forgetting the JSON body; content-type mismatches causing the body to be ignored.","solutions":["Send a JSON body such as {\"action\":\"suspend\"} with Content-Type: application/json","Use one of the supported actions: activate or suspend","Check the HTTP client actually serializes the request body"],"exampleFix":"// before\ncurl -X PUT .../process-definitions/myDef -H \"Content-Type: application/json\"\n// after\ncurl -X PUT .../process-definitions/myDef -H \"Content-Type: application/json\" -d '{\"action\":\"suspend\"}'","handlingStrategy":"validation","validationCode":"if (!body || !body.action) throw new Error('PUT process-definition requires a JSON body with an action field');","typeGuard":"const hasAction = (r) => r != null && typeof r.action === 'string' && r.action.length > 0;","tryCatchPattern":"try { await api.put(defUrl, { action: 'suspend' }); }\ncatch (e) { if (e.status === 400 && /No action found/.test(e.message)) fixRequestBody(e); else throw e; }","preventionTips":["Always send Content-Type: application/json with a serialized body","Test HTTP calls with curl including -d flag","Centralize request building in a typed client"],"tags":["rest","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-14T05:17:10.506Z"}