flowable/flowable-engine · error · FlowableIllegalArgumentException

Invalid action: '" + actionRequest.getAction() + "'.

Error message

Invalid action: '" + actionRequest.getAction() + "'.

What it means

After null-checking the body, executeProcessDefinitionAction dispatches on the 'action' string; only 'activate' and 'suspend' are recognized. Any other value falls through to this FlowableIllegalArgumentException.

Solutions

  1. Use exactly "suspend" or "activate" (lowercase) in the action field
  2. Consult ProcessDefinitionActionRequest constants ACTION_SUSPEND / ACTION_ACTIVATE
  3. Validate the action client-side before sending

Example fix

// before
{"action": "Suspend"}
// after
{"action": "suspend", "includeProcessInstances": true}
Defensive patterns

Strategy: validation

Validate before calling

const ACTIONS = ['activate','suspend'];
if (!ACTIONS.includes(action)) throw new Error(`action must be 'activate' or 'suspend', got: ${action}`);

Type guard

const isValidAction = (a) => a === 'activate' || a === 'suspend';

Try / catch

try { await api.put(defUrl, { action }); }
catch (e) { if (e.status === 400 && /Invalid action/.test(e.message)) fixActionName(e); else throw e; }

Prevention

When it happens

Trigger: PUT /repository/process-definitions/{id} with body {"action":"pause"} or any misspelled/unsupported action string.

Common situations: Typo in the action name; clients written against other engines' APIs using different verbs (e.g. 'disable'); case-sensitivity surprises ('Suspend' vs 'suspend').

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionResource.java:129

            // No need to re-fetch the ProcessDefinition entity, just update
            // category in response
            ProcessDefinitionResponse response = restResponseFactory.createProcessDefinitionResponse(processDefinition);
            response.setCategory(actionRequest.getCategory());
            return response;

        } else {
            // Actual action
            if (actionRequest.getAction() != null) {
                if (ProcessDefinitionActionRequest.ACTION_SUSPEND.equals(actionRequest.getAction())) {
                    return suspendProcessDefinition(processDefinition, actionRequest.isIncludeProcessInstances(), actionRequest.getDate());

                } else if (ProcessDefinitionActionRequest.ACTION_ACTIVATE.equals(actionRequest.getAction())) {
                    return activateProcessDefinition(processDefinition, actionRequest.isIncludeProcessInstances(), actionRequest.getDate());
                }
            }

            throw new FlowableIllegalArgumentException("Invalid action: '" + actionRequest.getAction() + "'.");
        }
    }
    
    @ApiOperation(value = "Get a process definition start form", tags = { "Process Definitions" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates request was successful and the process definition form is returned"),
            @ApiResponse(code = 404, message = "Indicates the requested process definition was not found.")
    })
    @GetMapping(value = "/repository/process-definitions/{processDefinitionId}/start-form", produces = "application/json")
    public String getProcessDefinitionStartForm(@ApiParam(name = "processDefinitionId") @PathVariable String processDefinitionId) {
        FormEngineConfigurationApi formEngineConfiguration = (FormEngineConfigurationApi) processEngineConfiguration.getEngineConfigurations().get(EngineConfigurationConstants.KEY_FORM_ENGINE_CONFIG);
        if (formEngineConfiguration == null) {
            return null;
        }
        FormRepositoryService formRepositoryService = formEngineConfiguration.getFormRepositoryService();
        if (formRepositoryService == null) {
            return null;
        }

View on GitHub (pinned to d6d39ce1c6)