diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.gitignore b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.gitignore
new file mode 100644
index 0000000000..afce51184c
--- /dev/null
+++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.gitignore
@@ -0,0 +1,2 @@
+/.aadlbin-gen/
+/instances/
diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.project b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.project
new file mode 100644
index 0000000000..1fac84d4b9
--- /dev/null
+++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/.project
@@ -0,0 +1,18 @@
+
+
+ issue2814
+
+
+
+
+
+ org.eclipse.xtext.ui.shared.xtextBuilder
+
+
+
+
+
+ org.osate.core.aadlnature
+ org.eclipse.xtext.ui.shared.xtextNature
+
+
diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/Issue2814.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/Issue2814.aadl
new file mode 100644
index 0000000000..cbde333d4f
--- /dev/null
+++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/Issue2814.aadl
@@ -0,0 +1,31 @@
+package Issue2814
+public
+ system s
+ end s;
+
+ system implementation s.i
+ annex EMV2 {**
+ use types ErrorLibrary;
+ use behavior Issue2814::machine;
+ component error behavior
+ events
+ event1: error event;
+ transitions
+ state1 -[event1]-> (
+ state2 {ServiceError, ItemTimingError} with 0.4,
+ state3 {CommonErrors} with 0.6
+ );
+ end component;
+ **};
+ end s.i;
+
+ annex EMV2 {**
+ error behavior machine
+ use types ErrorLibrary;
+ states
+ state1: initial state;
+ state2: state {CommonErrors};
+ state3: state {CommonErrors};
+ end behavior;
+ **};
+end Issue2814;
diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/ValidBranches.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/ValidBranches.aadl
new file mode 100644
index 0000000000..fd4f2045e0
--- /dev/null
+++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2814/ValidBranches.aadl
@@ -0,0 +1,34 @@
+package ValidBranches
+public
+ system s
+ annex EMV2 {**
+ use types ValidBranches;
+ use behavior ValidBranches::machine;
+ component error behavior
+ transitions
+ start -[event1]-> (
+ single {First} with 0.25,
+ product {First * Second} with 0.25,
+ start with 0.25,
+ same state with 0.25
+ );
+ end component;
+ **};
+ end s;
+
+ annex EMV2 {**
+ error types
+ First: type;
+ Second: type;
+ end types;
+ error behavior machine
+ use types ValidBranches;
+ events
+ event1: error event;
+ states
+ start: initial state;
+ single: state {First};
+ product: state {First, First * Second};
+ end behavior;
+ **};
+end ValidBranches;
diff --git a/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2814Test.java b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2814Test.java
new file mode 100644
index 0000000000..87955c9ffc
--- /dev/null
+++ b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2814Test.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file).
+ * All Rights Reserved.
+ *
+ * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
+ * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
+ * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
+ *
+ * This program includes and/or can make use of certain third party source code, object code, documentation and other
+ * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
+ * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
+ * conditions contained in any such Third Party Software or separate license file distributed with such Third Party
+ * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
+ * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
+ * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
+ */
+package org.osate.aadl2.errormodel.tests.issues;
+
+import java.util.ArrayList;
+
+import org.eclipse.xtext.testing.InjectWith;
+import org.eclipse.xtext.testing.XtextRunner;
+import org.eclipse.xtext.testing.validation.ValidationTestHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osate.aadl2.AadlPackage;
+import org.osate.aadl2.DefaultAnnexSubclause;
+import org.osate.aadl2.errormodel.tests.ErrorModelInjectorProvider;
+import org.osate.testsupport.AssertHelper;
+import org.osate.testsupport.TestHelper;
+import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelSubclause;
+
+import com.google.inject.Inject;
+import com.itemis.xtext.testing.FluentIssueCollection;
+import com.itemis.xtext.testing.XtextTest;
+
+@RunWith(XtextRunner.class)
+@InjectWith(ErrorModelInjectorProvider.class)
+public class Issue2814Test extends XtextTest {
+ private static final String PROJECT_LOCATION = "org.osate.aadl2.errormodel.tests/models/issue2814/";
+
+ @Inject
+ private TestHelper testHelper;
+
+ @Inject
+ private ValidationTestHelper validationHelper;
+
+ @Test
+ public void rejectMultipleTargetTypesAndTypeSets() throws Exception {
+ var result = issues = testHelper.testFile(PROJECT_LOCATION + "Issue2814.aadl");
+ var expected = new FluentIssueCollection(result.getResource(), new ArrayList<>(), new ArrayList<>());
+ var pkg = (AadlPackage) result.getResource().getContents().getFirst();
+ var annex = (ErrorModelSubclause) ((DefaultAnnexSubclause) pkg.getPublicSection().getOwnedClassifiers()
+ .get(1).getOwnedAnnexSubclauses().getFirst()).getParsedAnnexSubclause();
+ var branches = annex.getTransitions().getFirst().getDestinationBranches();
+ AssertHelper.assertError(branches.get(0), result.getIssues(), expected,
+ "Target state state2 may only have a single error type");
+ AssertHelper.assertError(branches.get(1), result.getIssues(), expected,
+ "Target state state3 may only have a single error type");
+ expected.sizeIs(2);
+ assertConstraints(expected);
+ }
+
+ @Test
+ public void acceptSingleTypesProductsAndImplicitTargets() {
+ validationHelper.assertNoIssues(testHelper.parseFile(PROJECT_LOCATION + "ValidBranches.aadl"));
+ }
+}
diff --git a/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java b/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java
index 821454b3d5..1baa0c9cc7 100644
--- a/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java
+++ b/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java
@@ -1121,10 +1121,16 @@ private void checkTransitionTargetTypes(TransitionBranch ebt) {
if (tt == null || tt.getTypeTokens().isEmpty()) {
return;
}
+ if (tt.getTypeTokens().size() > 1) {
+ error(ebt, "Target state " + ebs.getName() + " may only have a single error type");
+ }
TypeToken ebtargetTS = tt.getTypeTokens().get(0);
if (ebtargetTS == null) {
return;
}
+ if (!ebtargetTS.getType().isEmpty() && !(ebtargetTS.getType().getFirst() instanceof ErrorType)) {
+ error(ebt, "Target state " + ebs.getName() + " may only have a single error type");
+ }
if (ebsTS == null && ebtargetTS != null) {
error(ebt,
"Target state " + ebs.getName()