flowable/flowable-engine · error · FlowableException

The default BPMN parse handlers should only support one type

Error message

The default BPMN parse handlers should only support one type, but {class} supports {supportedTypes}. This is likely a programmatic error

What it means

During process engine configuration, ProcessEngineConfigurationImpl iterates the built-in (default) BPMN parse handlers and enforces the internal invariant that each handles exactly one BPMN element type, so custom handlers can replace defaults one-to-one. If a default handler reports getHandledTypes().size() != 1, this FlowableException is thrown listing the class and all its supported types, flagged as 'likely a programmatic error' — i.e. the shipped handler set (or an override of it) is corrupted or inconsistently extended.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java:1911

        // Replace any default handler if the user wants to replace them
        if (customDefaultBpmnParseHandlers != null) {

            Map<Class<?>, BpmnParseHandler> customParseHandlerMap = new HashMap<>();
            for (BpmnParseHandler bpmnParseHandler : customDefaultBpmnParseHandlers) {
                for (Class<?> handledType : bpmnParseHandler.getHandledTypes()) {
                    customParseHandlerMap.put(handledType, bpmnParseHandler);
                }
            }

            for (int i = 0; i < bpmnParserHandlers.size(); i++) {
                // All the default handlers support only one type
                BpmnParseHandler defaultBpmnParseHandler = bpmnParserHandlers.get(i);
                if (defaultBpmnParseHandler.getHandledTypes().size() != 1) {
                    StringBuilder supportedTypes = new StringBuilder();
                    for (Class<?> type : defaultBpmnParseHandler.getHandledTypes()) {
                        supportedTypes.append(" ").append(type.getCanonicalName()).append(" ");
                    }
                    throw new FlowableException("The default BPMN parse handlers should only support one type, but " + defaultBpmnParseHandler.getClass() + " supports " + supportedTypes
                        + ". This is likely a programmatic error");
                } else {
                    Class<?> handledType = defaultBpmnParseHandler.getHandledTypes().iterator().next();
                    if (customParseHandlerMap.containsKey(handledType)) {
                        BpmnParseHandler newBpmnParseHandler = customParseHandlerMap.get(handledType);
                        logger.info("Replacing default BpmnParseHandler {} with {}", defaultBpmnParseHandler.getClass().getName(), newBpmnParseHandler.getClass().getName());
                        bpmnParserHandlers.set(i, newBpmnParseHandler);
                    }
                }
            }
        }

        return bpmnParserHandlers;
    }

    public void initProcessDiagramGenerator() {
        if (processDiagramGenerator == null) {
            processDiagramGenerator = new DefaultProcessDiagramGenerator();

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Restore each default BpmnParseHandler so getHandledTypes() returns exactly one Class — split multi-type handlers into separate handlers
  2. Move multi-type or custom handlers out of the default handler set and register them via setPreBpmnParseHandlers()/setPostBpmnParseHandlers() instead
  3. Check for mixed Flowable/Activiti jar versions on the classpath and align to a single flowable-engine version
  4. If you forked the engine, diff your parse handlers against the upstream release to find the invariant violation

Example fix

// before
class MyHandler implements BpmnParseHandler {
  public Collection<Class<? extends BaseElement>> getHandledTypes() {
    return Arrays.asList(StartEvent.class, EndEvent.class); // 2 types
  }
}

// after
class MyStartHandler implements BpmnParseHandler {
  public Collection<Class<? extends BaseElement>> getHandledTypes() {
    return Collections.singletonList(StartEvent.class); // exactly 1
  }
}
class MyEndHandler implements BpmnParseHandler {
  public Collection<Class<? extends BaseElement>> getHandledTypes() {
    return Collections.singletonList(EndEvent.class);
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before building the engine, when supplying custom parse handlers
List<BpmnParseHandler> handlers = processEngineConfiguration.getBpmnParseHandlers();
for (BpmnParseHandler h : handlers) {
  if (h.getHandledTypes() == null || h.getHandledTypes().size() != 1) {
    throw new IllegalStateException(h.getClass().getName()
        + " must handle exactly one BPMN type, got "
        + (h.getHandledTypes() == null ? 0 : h.getHandledTypes().size()));
  }
}

Type guard

boolean isSingleTypeHandler(BpmnParseHandler h) {
  return h != null && h.getHandledTypes() != null && h.getHandledTypes().size() == 1;
}

Try / catch

try {
  return processEngineConfiguration.buildProcessEngine();
} catch (FlowableException e) {
  if (e.getMessage() != null && e.getMessage().contains("should only support one type")) {
    throw new IllegalStateException("Default BPMN parse handler set corrupted; "
        + "check flowable jar versions and custom handler registration", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Bootstrapping the engine (buildProcessEngine) with a modified/overridden default parse-handler list where a handler's getHandledTypes() returns zero or multiple types; subclassing or repackaging BpmnParseHandler implementations into the default set; classpath shadowing where mixed flowable jar versions yield handlers built for multiple types.

Common situations: Custom fork of flowable-engine where a default handler was edited to handle several BPMN element types; accidentally adding custom handlers to the default handler list instead of preBpmnParseHandlers/postBpmnParseHandlers; mixed Flowable/Activiti jars on the classpath; a bad merge when upgrading Flowable versions.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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