diff --git a/app/comp/res_but.py b/app/comp/res_but.py
index 9e3af6f75dc47e0d1319e8eb7a2a36966886a0ca..502cd980cfd8a749a23bc368335b5b02b89aa01c 100644
--- a/app/comp/res_but.py
+++ b/app/comp/res_but.py
@@ -159,6 +159,8 @@ class ResultatsSemestreBUT(NotesTableCompat):
         # moyenne sur les UE:
         if len(self.sem_cube[etud_idx, mod_idx]):
             return np.nanmean(self.sem_cube[etud_idx, mod_idx])
+            # note: si toutes les valeurs sont nan, on va déclencher ici
+            # un RuntimeWarning: Mean of empty slice
         return np.nan
 
     def compute_etud_ue_coef(self, etudid: int, ue: UniteEns) -> float:
diff --git a/app/static/js/table_recap.js b/app/static/js/table_recap.js
index aa322de2285f985be413182e76937137512c45c3..d2d8840e59e24520d371dd903d07acfa1f2c7b41 100644
--- a/app/static/js/table_recap.js
+++ b/app/static/js/table_recap.js
@@ -146,10 +146,13 @@ $(function () {
                     action: toggle_col_but_visibility,
                 });
             }
-            buttons.push({ // modules vides
-                text: '<span data-group="col_empty">Vides</span>',
-                action: toggle_col_but_visibility,
-            });
+            // S'il y a des colonnes vides:
+            if ($('table.table_recap td.col_empty').length > 0) {
+                buttons.push({ // modules vides
+                    text: '<span data-group="col_empty">Vides</span>',
+                    action: toggle_col_but_visibility,
+                });
+            }
             // Boutons admission (pas en jury)
             if (!$('table.table_recap').hasClass("jury")) {
                 buttons.push(