diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py
index 7bcfcd78d..ab5292a78 100644
--- a/app/scodoc/sco_edit_module.py
+++ b/app/scodoc/sco_edit_module.py
@@ -289,7 +289,10 @@ def module_create(
                     "type": "int",
                     "title": "UE de rattachement",
                     "explanation": "utilisée notamment pour les malus",
-                    "labels": [f"{u.acronyme} {u.titre}" for u in ues],
+                    "labels": [
+                        f"S{u.semestre_idx if u.semestre_idx is not None else '.'} / {u.acronyme} {u.titre}"
+                        for u in ues
+                    ],
                     "allowed_values": [u.id for u in ues],
                 },
             ),
diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py
index 6de171d16..619e2d078 100644
--- a/app/scodoc/sco_formsemestre_edit.py
+++ b/app/scodoc/sco_formsemestre_edit.py
@@ -118,10 +118,16 @@ def formsemestre_editwithmodules(formsemestre_id):
         vals = scu.get_request_args()
         if not vals.get("tf_submitted", False):
             H.append(
-                """<p class="help">Seuls les modules cochés font partie de ce semestre. Pour les retirer, les décocher et appuyer sur le bouton "modifier".
-</p>
-<p class="help">Attention : s'il y a déjà des évaluations dans un module, il ne peut pas être supprimé !</p>
-<p class="help">Les modules ont toujours un responsable. Par défaut, c'est le directeur des études.</p>"""
+                """<p class="help">Seuls les modules cochés font partie de ce semestre. 
+                Pour les retirer, les décocher et appuyer sur le bouton "modifier".
+                </p>
+                <p class="help">Attention : s'il y a déjà des évaluations dans un module, 
+                il ne peut pas être supprimé !</p>
+                <p class="help">Les modules ont toujours un responsable. 
+                Par défaut, c'est le directeur des études.</p>
+                <p class="help">Un semestre ne peut comporter qu'une seule UE "bonus
+                sport/culture"</p>
+            """
             )
 
     return "\n".join(H) + html_sco_header.sco_footer()
@@ -739,6 +745,7 @@ def do_formsemestre_createwithmodules(edit=False):
         # Modules sélectionnés:
         # (retire le "MI" du début du nom de champs)
         module_ids_checked = [int(x[2:]) for x in tf[2]["tf-checked"]]
+        _formsemestre_check_ue_bonus_unicity(module_ids_checked)
         if not edit:
             if formation.is_apc():
                 _formsemestre_check_module_list(
@@ -882,6 +889,18 @@ def _formsemestre_check_module_list(module_ids, semestre_idx):
         )
 
 
+def _formsemestre_check_ue_bonus_unicity(module_ids):
+    """Vérifie qu'il n'y a qu'une seule UE bonus associée aux modules choisis"""
+    ues = [Module.query.get_or_404(module_id).ue for module_id in module_ids]
+    ues_bonus = {ue.id for ue in ues if ue.type == sco_codes_parcours.UE_SPORT}
+    if len(ues_bonus) > 1:
+        raise ScoValueError(
+            """Les modules de bonus sélectionnés ne sont pas tous dans la même UE bonus.
+            Changez la sélection ou modifiez la structure du programme de formation.""",
+            dest_url="javascript:history.back();",
+        )
+
+
 def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del):
     """Delete moduleimpls
     module_ids_to_del: list of module_id (warning: not moduleimpl)