diff --git a/CHANGELOG.md b/CHANGELOG.md
index 596e3fa553480d3a1943da36e62d71518b578fdc..9a30c0c59307214535ed1f5727861bb7b6b21bfe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,14 +21,13 @@
     - If the file is not present or the `success` field is not present:
         - The exercise will be considered as valid if the container exit code is 0
         - The `results.json` file will be construct / completed with the container exit code
-    - If the file is present, the exercise will be considered as valid
     - The `volume` argument of `dojo_assignment.json` is now optional (if the teaching staff don't want to provide `results.json` file or other files)
 
 ### 🔨 Internal / Developers
 - Enhancement in pipelines by splitting them into several files
 
 
-## 2.1.0 (?)
+## 2.1.0 (2023-09-29)
 
 ### 🎨 Interface
 - **💥 Breaking:** Renamed `dojo.enonce` (or `dojo.assignment`) file to `dojo_assignment.json`
diff --git a/ExerciseChecker/src/app.ts b/ExerciseChecker/src/app.ts
index 3d1df1d5211e9a544a1e773a05fab76fb0687e1f..1f025d2a7d79a5f8d7d11a35c57cd2568dcc5c54 100644
--- a/ExerciseChecker/src/app.ts
+++ b/ExerciseChecker/src/app.ts
@@ -7,23 +7,23 @@ require('dotenv').config({
                          });
 require('./shared/helpers/TypeScriptExtensions'); // ATTENTION : This line MUST be the second of this file
 
-import ClientsSharedConfig         from './sharedByClients/config/ClientsSharedConfig';
-import Styles                      from './types/Style';
-import Icon                        from './sharedByClients/types/Icon';
-import RecursiveFilesStats         from './shared/helpers/recursiveFilesStats/RecursiveFilesStats';
-import Toolbox                     from './shared/helpers/Toolbox';
-import ExerciseCheckerError        from './shared/types/Dojo/ExerciseCheckerError';
-import { exec }                    from 'child_process';
-import util                        from 'util';
-import fs                          from 'fs-extra';
-import HttpManager                 from './managers/HttpManager';
-import DojoBackendManager          from './managers/DojoBackendManager';
-import Config                      from './config/Config';
-import ArchiveHelper               from './shared/helpers/ArchiveHelper';
-import ExerciseDockerCompose       from './sharedByClients/helpers/Dojo/ExerciseDockerCompose';
-import ExerciseResultsValidation   from './sharedByClients/helpers/Dojo/ExerciseResultsValidation';
-import ExerciseAssignment          from './sharedByClients/models/ExerciseAssignment';
-import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsSharedExerciseHelper';
+import ClientsSharedConfig                  from './sharedByClients/config/ClientsSharedConfig';
+import Styles                               from './types/Style';
+import Icon                                 from './sharedByClients/types/Icon';
+import RecursiveFilesStats                  from './shared/helpers/recursiveFilesStats/RecursiveFilesStats';
+import Toolbox                              from './shared/helpers/Toolbox';
+import ExerciseCheckerError                 from './shared/types/Dojo/ExerciseCheckerError';
+import { exec }                             from 'child_process';
+import util                                 from 'util';
+import fs                                   from 'fs-extra';
+import HttpManager                          from './managers/HttpManager';
+import DojoBackendManager                   from './managers/DojoBackendManager';
+import Config                               from './config/Config';
+import ArchiveHelper                        from './shared/helpers/ArchiveHelper';
+import ExerciseDockerCompose                from './sharedByClients/helpers/Dojo/ExerciseDockerCompose';
+import ExerciseResultsSanitizerAndValidator from './sharedByClients/helpers/Dojo/ExerciseResultsSanitizerAndValidator';
+import ExerciseAssignment                   from './sharedByClients/models/ExerciseAssignment';
+import ClientsSharedExerciseHelper          from './sharedByClients/helpers/Dojo/ClientsSharedExerciseHelper';
 
 
 (async () => {
@@ -35,7 +35,10 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
 
     let exerciseAssignment: ExerciseAssignment | undefined;
     let exerciseDockerCompose: ExerciseDockerCompose;
-    let exerciseResultsValidation: ExerciseResultsValidation;
+    let exerciseResultsValidation: ExerciseResultsSanitizerAndValidator;
+
+    let haveResultsVolume: boolean;
+
 
     /*
      //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 1:
@@ -55,6 +58,8 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
             fs.mkdirSync(path.dirname(filePath), { recursive: true });
             fs.writeFileSync(filePath, immutableFile.content, { encoding: 'base64' });
         });
+
+        haveResultsVolume = exerciseAssignment.assignmentFile.result.volume !== undefined;
     }
 
 
@@ -65,12 +70,16 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
      - Get logs from linked services
      */
     {
+        let composeFileOverride: string[] = [];
         const composeOverridePath: string = path.join(Config.folders.project, 'docker-compose-override.yml');
+        if ( haveResultsVolume ) {
+            const composeOverride = fs.readFileSync(path.join(__dirname, '../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', exerciseAssignment.assignmentFile.result.volume!).replace('{{MOUNT_PATH}}', Config.folders.resultsExercise);
+            fs.writeFileSync(composeOverridePath, composeOverride);
 
-        const composeOverride = fs.readFileSync(path.join(__dirname, '../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', exerciseAssignment.assignmentFile.result.volume).replace('{{MOUNT_PATH}}', Config.folders.resultsExercise);
-        fs.writeFileSync(composeOverridePath, composeOverride);
+            composeFileOverride = [ composeOverridePath ];
+        }
 
-        exerciseDockerCompose = new ExerciseDockerCompose(ClientsSharedConfig.dockerCompose.projectName, exerciseAssignment.assignmentFile, Config.folders.project, [ composeOverridePath ]);
+        exerciseDockerCompose = new ExerciseDockerCompose(ClientsSharedConfig.dockerCompose.projectName, exerciseAssignment.assignmentFile, Config.folders.project, composeFileOverride);
 
         try {
             await new Promise<void>((resolve, reject) => {
@@ -92,7 +101,7 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
             });
         } catch ( error ) { }
 
-        fs.rmSync(composeOverridePath);
+        fs.rmSync(composeOverridePath, { force: true });
         fs.writeFileSync(path.join(Config.folders.resultsDojo, 'dockerComposeLogs.txt'), exerciseDockerCompose.allLogs);
 
         if ( !exerciseDockerCompose.success ) {
@@ -104,7 +113,7 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
 
     //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 3: Check content requirements and content size
     {
-        exerciseResultsValidation = new ExerciseResultsValidation(Config.folders.resultsDojo, Config.folders.resultsExercise);
+        exerciseResultsValidation = new ExerciseResultsSanitizerAndValidator(Config.folders.resultsDojo, Config.folders.resultsExercise, exerciseDockerCompose.exitCode);
 
         try {
             await new Promise<void>((resolve) => {
@@ -146,7 +155,7 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
                 liteStats               : true
             });
 
-            await DojoBackendManager.sendResults(exerciseDockerCompose.exitCode, commit, exerciseResultsValidation.exerciseResults!, files, await ArchiveHelper.getBase64(Config.folders.resultsVolume));
+            await DojoBackendManager.sendResults(exerciseDockerCompose.exitCode, commit, exerciseResultsValidation.exerciseResults, files, await ArchiveHelper.getBase64(Config.folders.resultsVolume));
         } catch ( error ) {
             console.error(Styles.ERROR(`${ Icon.ERROR } Error while uploading the results`));
             console.error(JSON.stringify(error));
@@ -161,7 +170,7 @@ import ClientsSharedExerciseHelper from './sharedByClients/helpers/Dojo/ClientsS
      - Exit with container exit code
      */
     {
-        ClientsSharedExerciseHelper.displayExecutionResults(exerciseResultsValidation.exerciseResults!, exerciseDockerCompose.exitCode, Styles, `\n\n${ Icon.INFO }️ More detailed logs and resources may be available in artifacts`);
+        ClientsSharedExerciseHelper.displayExecutionResults(exerciseResultsValidation.exerciseResults, exerciseDockerCompose.exitCode, Styles, `\n\n${ Icon.INFO }️ More detailed logs and resources may be available in artifacts`);
 
         process.exit(exerciseDockerCompose.exitCode);
     }
diff --git a/ExerciseChecker/src/shared b/ExerciseChecker/src/shared
index 8d7e3ca0cca10e874ac48e19e47da8a1491ccba7..80820496589a0c742f92cacb092e87c62f91cce1 160000
--- a/ExerciseChecker/src/shared
+++ b/ExerciseChecker/src/shared
@@ -1 +1 @@
-Subproject commit 8d7e3ca0cca10e874ac48e19e47da8a1491ccba7
+Subproject commit 80820496589a0c742f92cacb092e87c62f91cce1
diff --git a/ExerciseChecker/src/sharedByClients b/ExerciseChecker/src/sharedByClients
index 4ff3846e9415a6122b0b966be089eec3f0117f4f..bef7705ef60e85e4a2bf1f9768bb242d18cc4249 160000
--- a/ExerciseChecker/src/sharedByClients
+++ b/ExerciseChecker/src/sharedByClients
@@ -1 +1 @@
-Subproject commit 4ff3846e9415a6122b0b966be089eec3f0117f4f
+Subproject commit bef7705ef60e85e4a2bf1f9768bb242d18cc4249