diff --git a/arkindex/training/api.py b/arkindex/training/api.py
index b0b38db5f8c8d10002832fc61ffcf7eefe238984..cdecc15cd2fc4b67cd74a1429b51c2bdddd23b50 100644
--- a/arkindex/training/api.py
+++ b/arkindex/training/api.py
@@ -561,7 +561,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView):
     put=extend_schema(
         description=dedent(
             """
-            Update a dataset.
+            Update a dataset. The dataset must not be in `complete` state.
 
             The sets array can only be updated following those cases:
               * Adding or removing sets, nothing specific is done.
@@ -575,7 +575,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView):
     patch=extend_schema(
         description=dedent(
             """
-            Partially update a dataset.
+            Partially update a dataset. The dataset must not be in `complete` state.
 
             The sets array can only be updated following those cases:
               * Adding or removing sets, nothing specific is done.
@@ -618,6 +618,10 @@ class DatasetUpdate(ACLMixin, RetrieveUpdateDestroyAPIView):
         if not self.has_access(obj.corpus, role.value):
             raise PermissionDenied(detail=f'You do not have {str(role).lower()} access to corpus {obj.corpus.name}.')
 
+        # Prevent editing anything on a complete dataset
+        if obj.state == DatasetState.Complete:
+            raise ValidationError(detail='This dataset is in complete state and cannot be modified anymore.')
+
     def perform_destroy(self, dataset):
         dataset.dataset_elements.all().delete()
         super().perform_destroy(dataset)
diff --git a/arkindex/training/tests/test_datasets_api.py b/arkindex/training/tests/test_datasets_api.py
index 2733436554f2239b5735fa2125a2d700815ec89a..5216495af92fe13ae5ecf16cb9d85aba5afeb291 100644
--- a/arkindex/training/tests/test_datasets_api.py
+++ b/arkindex/training/tests/test_datasets_api.py
@@ -711,10 +711,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
             (build, build) : True,
             (build, complete) : True,
             (build, error): True,
-            (complete, op): False,
-            (complete, build) : False,
-            (complete, complete) : True,
-            (complete, error): False,
             (error, op): False,
             (error, build) : True,
             (error, complete) : False,
@@ -745,6 +741,29 @@ class TestDatasetsAPI(FixtureAPITestCase):
                         {'state': [f'Transition from {state_from} to {state_to} is not allowed.']}
                     )
 
+    def test_update_complete_forbidden(self):
+        self.dataset.state = DatasetState.Complete
+        self.dataset.save()
+        self.client.force_login(self.user)
+        for new_state in DatasetState:
+            with self.subTest(new_state=new_state):
+                with self.assertNumQueries(6):
+                    response = self.client.put(
+                        reverse('api:dataset-update', kwargs={'pk': self.dataset.pk}),
+                        data={
+                            'name': 'AA',
+                            'description': 'BB',
+                            'sets': self.dataset.sets + ['CC'],
+                            'state': new_state.value,
+                        },
+                        format='json'
+                    )
+                    self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+                self.assertListEqual(
+                    response.json(),
+                    ['This dataset is in complete state and cannot be modified anymore.'],
+                )
+
     def test_update_ponos_task_state_requires_dataset_in_process(self):
         self.process.process_datasets.all().delete()
         with self.assertNumQueries(7):
@@ -962,10 +981,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
             (build, build) : True,
             (build, complete) : True,
             (build, error): True,
-            (complete, op): False,
-            (complete, build) : False,
-            (complete, complete) : True,
-            (complete, error): False,
             (error, op): False,
             (error, build) : True,
             (error, complete) : False,
@@ -996,6 +1011,29 @@ class TestDatasetsAPI(FixtureAPITestCase):
                         {'state': [f'Transition from {state_from} to {state_to} is not allowed.']}
                     )
 
+    def test_partial_update_complete_forbidden(self):
+        self.dataset.state = DatasetState.Complete
+        self.dataset.save()
+        self.client.force_login(self.user)
+        for new_state in DatasetState:
+            with self.subTest(new_state=new_state):
+                with self.assertNumQueries(6):
+                    response = self.client.patch(
+                        reverse('api:dataset-update', kwargs={'pk': self.dataset.pk}),
+                        data={
+                            'name': 'AA',
+                            'description': 'BB',
+                            'sets': self.dataset.sets + ['CC'],
+                            'state': new_state.value,
+                        },
+                        format='json'
+                    )
+                    self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+                self.assertListEqual(
+                    response.json(),
+                    ['This dataset is in complete state and cannot be modified anymore.'],
+                )
+
     # RetrieveDataset
 
     def test_retrieve_requires_login(self):