flowable/flowable-engine · error · ActivitiException
The default BPMN parse handlers should only support one type
Error message
The default BPMN parse handlers should only support one type, but ${defaultBpmnParseHandler.getClass()} supports ${supportedTypes}. This is likely a programmatic error What it means
Default BpmnParseHandlers are expected to each declare exactly one handled model type so the engine can map type->handler and allow per-type replacement by custom handlers. If a default handler reports getHandledTypes().size() != 1 during bpmn parser initialization, the engine throws this ActivitiException as an internal consistency check.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java:1257
// 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 ActivitiException("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);
}
}
}
}
// History
bpmnParserHandlers.addAll(getDefaultHistoryParseHandlers());
return bpmnParserHandlers;
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Ensure every handler in the default list declares exactly one handled type; move multi-type handlers to customPreBpmnParseHandlers/customPostBpmnParseHandlers instead
- Implement getHandledTypes() returning a single-element set (e.g. Collections.singletonList(ServiceTask.class)) for default handlers
- Verify you are not mixing handler classes from different Activiti versions on the classpath
Example fix
// before
@Override
public Set<Class<? extends BaseElement>> getHandledTypes() {
return new HashSet<>(Arrays.asList(ServiceTask.class, UserTask.class));
}
// after
@Override
public Set<Class<? extends BaseElement>> getHandledTypes() {
return Collections.singleton(ServiceTask.class); // default list: one type only
} Defensive patterns
Strategy: validation
Validate before calling
for (BpmnParseHandler h : cfg.getDefaultBpmnParseHandlers()) {
if (h.getHandledTypes().size() != 1) {
throw new IllegalStateException(h.getClass().getName() + " must handle exactly one type to sit in the default list");
}
} Try / catch
try {
processEngine = cfg.buildProcessEngine();
} catch (ActivitiException e) {
if (e.getMessage().contains("should only support one type")) {
throw new ConfigurationException("Move multi-type handlers to customPre/PostBpmnParseHandlers", e);
} else throw e;
} Prevention
- Default handler list: one handled type per handler, always
- Use customPreBpmnParseHandlers/customPostBpmnParseHandlers for multi-type handlers
- Keep getHandledTypes() returning Collections.singleton(...) in default handlers
- Don't mix handler classes across Activiti versions on the classpath
When it happens
Trigger: A default handler class (or a substitute injected into the default handler list via configuration) whose getHandledTypes() returns zero or multiple types — e.g. a custom implementation placed in defaultBpmnParseHandlers, or a modified/buggy handler in the engine jar.
Common situations: Extending the engine by overriding getDefaultBpmnParseHandlers and inserting a multi-type custom handler by mistake; custom classloader picking a patched handler; engine jar version mixing.
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
- The default BPMN parse handlers should only support one type
- Activity ${modelActivity.getId()} needed for multi instance
- No execution found for sub process of boundary cancel event
- Error while parsing BPMN model.
- Errors while parsing:\n" + errorBuilder
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2572473778e6e443.
Report an issue: GitHub.