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

  1. Ensure every handler in the default list declares exactly one handled type; move multi-type handlers to customPreBpmnParseHandlers/customPostBpmnParseHandlers instead
  2. Implement getHandledTypes() returning a single-element set (e.g. Collections.singletonList(ServiceTask.class)) for default handlers
  3. 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

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


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