{"record":{"id":"2572473778e6e443","repo":"flowable/flowable-engine","slug":"the-default-bpmn-parse-handlers-should-only-suppor-257247","errorCode":null,"errorMessage":"The default BPMN parse handlers should only support one type, but ${defaultBpmnParseHandler.getClass()} supports ${supportedTypes}. This is likely a programmatic error","messagePattern":"The default BPMN parse handlers should only support one type, but (.+?) supports (.+?)\\. This is likely a programmatic error","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java","lineNumber":1257,"sourceCode":"        // Replace any default handler if the user wants to replace them\n        if (customDefaultBpmnParseHandlers != null) {\n\n            Map<Class<?>, BpmnParseHandler> customParseHandlerMap = new HashMap<>();\n            for (BpmnParseHandler bpmnParseHandler : customDefaultBpmnParseHandlers) {\n                for (Class<?> handledType : bpmnParseHandler.getHandledTypes()) {\n                    customParseHandlerMap.put(handledType, bpmnParseHandler);\n                }\n            }\n\n            for (int i = 0; i < bpmnParserHandlers.size(); i++) {\n                // All the default handlers support only one type\n                BpmnParseHandler defaultBpmnParseHandler = bpmnParserHandlers.get(i);\n                if (defaultBpmnParseHandler.getHandledTypes().size() != 1) {\n                    StringBuilder supportedTypes = new StringBuilder();\n                    for (Class<?> type : defaultBpmnParseHandler.getHandledTypes()) {\n                        supportedTypes.append(\" \").append(type.getCanonicalName()).append(\" \");\n                    }\n                    throw new ActivitiException(\"The default BPMN parse handlers should only support one type, but \" + defaultBpmnParseHandler.getClass()\n                            + \" supports \" + supportedTypes + \". This is likely a programmatic error\");\n                } else {\n                    Class<?> handledType = defaultBpmnParseHandler.getHandledTypes().iterator().next();\n                    if (customParseHandlerMap.containsKey(handledType)) {\n                        BpmnParseHandler newBpmnParseHandler = customParseHandlerMap.get(handledType);\n                        LOGGER.info(\"Replacing default BpmnParseHandler {} with {}\", defaultBpmnParseHandler.getClass().getName(), newBpmnParseHandler.getClass()\n                                .getName());\n                        bpmnParserHandlers.set(i, newBpmnParseHandler);\n                    }\n                }\n            }\n        }\n\n        // History\n        bpmnParserHandlers.addAll(getDefaultHistoryParseHandlers());\n\n        return bpmnParserHandlers;\n    }","sourceCodeStart":1239,"sourceCodeEnd":1275,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java#L1239-L1275","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n@Override\npublic Set<Class<? extends BaseElement>> getHandledTypes() {\n  return new HashSet<>(Arrays.asList(ServiceTask.class, UserTask.class));\n}\n// after\n@Override\npublic Set<Class<? extends BaseElement>> getHandledTypes() {\n  return Collections.singleton(ServiceTask.class); // default list: one type only\n}","handlingStrategy":"validation","validationCode":"for (BpmnParseHandler h : cfg.getDefaultBpmnParseHandlers()) {\n  if (h.getHandledTypes().size() != 1) {\n    throw new IllegalStateException(h.getClass().getName() + \" must handle exactly one type to sit in the default list\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  processEngine = cfg.buildProcessEngine();\n} catch (ActivitiException e) {\n  if (e.getMessage().contains(\"should only support one type\")) {\n    throw new ConfigurationException(\"Move multi-type handlers to customPre/PostBpmnParseHandlers\", e);\n  } else throw e;\n}","preventionTips":["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"],"tags":["activiti","bpmn","parsing","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}