flowable/flowable-engine · warning · FlowableConflictException

Process definition with id '" + processDefinition.getId() +…

Error message

Process definition with id '" + processDefinition.getId() + " ' is already active

What it means

activateProcessDefinition checks repositoryService.isProcessDefinitionSuspended first; if the definition is not suspended, activating it is a no-op conflict and Flowable throws FlowableConflictException (HTTP 409). This guards against redundant state transitions.

Solutions

  1. Check suspension state first (GET definition, suspended flag) and skip activation if already active
  2. Catch FlowableConflictException / HTTP 409 and treat as success in idempotent automation
  3. Use the date parameter for scheduled activation instead of repeated calls

Example fix

// before
put(id, {"action":"activate"}); // 409 if already active
// after
if (def.suspended) put(id, {"action":"activate"});
Defensive patterns

Strategy: validation

Validate before calling

const def = await api.getProcessDefinition(defId);
if (!def.suspended) return { skipped: true, reason: 'already active' };

Type guard

const needsActivation = (def) => def != null && def.suspended === true;

Try / catch

try { await api.activateProcessDefinition(defId); }
catch (e) { if (e.status === 409) return { skipped: true }; throw e; }

Prevention

When it happens

Trigger: PUT /repository/process-definitions/{id} with {"action":"activate"} on a definition that is already active.

Common situations: Retry logic re-sending activate after a first success; race between two administrators; scheduled activation scripts running twice.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

                    
                } else {
                    formInfo = formRepositoryService.getFormModelByKey(startEvent.getFormKey(), processDefinition.getTenantId(),
                            processEngineConfiguration.isFallbackToDefaultTenant());
                }
            }
        }

        if (formInfo == null) {
            // Definition found, but no form attached
            throw new FlowableObjectNotFoundException("Process definition does not have a form defined: " + processDefinition.getId());
        }
        
        return formInfo;
    }

    protected ProcessDefinitionResponse activateProcessDefinition(ProcessDefinition processDefinition, boolean suspendInstances, Date date) {
        if (!repositoryService.isProcessDefinitionSuspended(processDefinition.getId())) {
            throw new FlowableConflictException("Process definition with id '" + processDefinition.getId() + " ' is already active");
        }
        repositoryService.activateProcessDefinitionById(processDefinition.getId(), suspendInstances, date);

        ProcessDefinitionResponse response = restResponseFactory.createProcessDefinitionResponse(processDefinition);

        // No need to re-fetch the ProcessDefinition, just alter the suspended
        // state of the result-object
        response.setSuspended(false);
        return response;
    }

    protected ProcessDefinitionResponse suspendProcessDefinition(ProcessDefinition processDefinition, boolean suspendInstances, Date date) {
        if (repositoryService.isProcessDefinitionSuspended(processDefinition.getId())) {
            throw new FlowableConflictException("Process definition with id '" + processDefinition.getId() + " ' is already suspended");
        }
        repositoryService.suspendProcessDefinitionById(processDefinition.getId(), suspendInstances, date);

        ProcessDefinitionResponse response = restResponseFactory.createProcessDefinitionResponse(processDefinition);

View on GitHub (pinned to d6d39ce1c6)