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
- Restore each default BpmnParseHandler so getHandledTypes() returns exactly one Class — split multi-type handlers into separate handlers
- Move multi-type or custom handlers out of the default handler set and register them via setPreBpmnParseHandlers()/setPostBpmnParseHandlers() instead
- Check for mixed Flowable/Activiti jar versions on the classpath and align to a single flowable-engine version
- 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
- Never add multi-type handlers to the default handler set; use preBpmnParseHandlers/postBpmnParseHandlers
- Keep one flowable-engine version on the classpath (no mixed Activiti/Flowable jars)
- If forking handlers, keep the one-handled-type-per-default-handler invariant
- Add a configuration smoke test that builds the engine in CI
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
- Cannot parse EL property ${PROP_CACHE_SIZE}
- decisionTableReferenceKey is a required field extension for
- Could not resolve key for: ${eventDefinitionKey} for ${execu
- The default BPMN parse handlers should only support one type
- no org.flowable.app.engine.AppEngine defined in the applicat
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5463d1d29ac2f2f9.
Report an issue: GitHub.