{"record":{"id":"f4786098ab134589","repo":"flowable/flowable-engine","slug":"activity-id-has-duplicate-transition-trans","errorCode":null,"errorMessage":"activity '${id}' has duplicate transition '${transitionId}'","messagePattern":"activity '(.+?)' has duplicate transition '(.+?)'","errorType":"exception","errorClass":"PvmException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/process/ActivityImpl.java","lineNumber":77,"sourceCode":"        this.failedJobRetryTimeCycleValue = failedJobRetryTimeCycleValue;\n    }\n\n    public TransitionImpl createOutgoingTransition() {\n        return createOutgoingTransition(null);\n    }\n\n    public TransitionImpl createOutgoingTransition(String transitionId) {\n        return createOutgoingTransition(transitionId, null);\n    }\n\n    public TransitionImpl createOutgoingTransition(String transitionId, Expression skipExpression) {\n        TransitionImpl transition = new TransitionImpl(transitionId, skipExpression, processDefinition);\n        transition.setSource(this);\n        outgoingTransitions.add(transition);\n\n        if (transitionId != null) {\n            if (namedOutgoingTransitions.containsKey(transitionId)) {\n                throw new PvmException(\"activity '\" + id + \"' has duplicate transition '\" + transitionId + \"'\");\n            }\n            namedOutgoingTransitions.put(transitionId, transition);\n        }\n\n        return transition;\n    }\n\n    @Override\n    public TransitionImpl findOutgoingTransition(String transitionId) {\n        return namedOutgoingTransitions.get(transitionId);\n    }\n\n    @Override\n    public String toString() {\n        return \"Activity(\" + id + \")\";\n    }\n\n    public ActivityImpl getParentActivity() {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/process/ActivityImpl.java#L59-L95","documentation":"PvmException thrown by ActivityImpl.createOutgoingTransition when a transition with the same non-null transitionId already exists on this activity. The activity maintains a namedOutgoingTransitions map for id-based lookup, which must stay unique per activity. Adding a second transition with the same id would corrupt that index.","triggerScenarios":"Calling activity.createOutgoingTransition(\"sameId\", ...) twice (or the builder's transition(...) helper twice with the same id) on one activity.","commonSituations":"Duplicate transition ids in BPMN XML (e.g. two sequence flows from the same gateway/activity with the same id), or programmatic building that reuses ids across loops.","solutions":["Give each outgoing transition a unique id on the activity, or pass null when an id is not needed.","Fix the BPMN source so sequence flow ids are unique per source element.","Deduplicate transition definitions before building (e.g. in a model importer)."],"exampleFix":"// before\nactivity.createOutgoingTransition(\"flow1\", null, \"a\");\nactivity.createOutgoingTransition(\"flow1\", null, \"b\"); // duplicate\n// after\nactivity.createOutgoingTransition(\"flow1\", null, \"a\");\nactivity.createOutgoingTransition(\"flow2\", null, \"b\");","handlingStrategy":"validation","validationCode":"Set<String> usedIds = new HashSet<>();\nif (!usedIds.add(transitionId)) {\n  throw new IllegalArgumentException(\"duplicate outgoing transition id '\" + transitionId + \"' on activity \" + id);\n}\nactivity.createOutgoingTransition(transitionId, skipExpression, destination);","typeGuard":null,"tryCatchPattern":"try {\n  activity.createOutgoingTransition(transitionId, null, dest);\n} catch (PvmException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"duplicate transition\")) {\n    // reuse or generate a unique id\n    activity.createOutgoingTransition(transitionId + \"-\" + UUID.randomUUID(), null, dest);\n  }\n}","preventionTips":["Enforce unique sequence-flow ids per source element when importing BPMN.","Pass null as transitionId when a named transition is not required.","Validate BPMN ids for global uniqueness before deployment."],"tags":["java","pvm","duplicate-id","process-model"],"backgroundTag":"invalid-identifier-format","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}