diff --git a/src/nub.ts b/src/nub.ts
index 3231fdc5354c9b4747f42f205156dc39e653b114..bec72f3c0299b367949838db28cdf9bca2d140e2 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -682,10 +682,10 @@ export abstract class Nub extends ComputeNode implements IObservable {
      * Returns true if all parameters are valid; used to check validity of
      * parameters linked to Nub results
      */
-    public isComputable() {
+    public isComputable(force: boolean = false) {
         let valid = true;
         for (const p of this.prms) {
-            valid = valid && p.isValid;
+            valid = valid && p.computeValidity(force);
         }
         return valid;
     }
diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts
index b47b066b0ef7ffa4f636f9e6593fcd838fab5b11..cf8cb3bfc3285b22d8dc96683d266b7bb6a255f6 100644
--- a/src/param/param-definition.ts
+++ b/src/param/param-definition.ts
@@ -656,17 +656,21 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
         return this.isMinMaxDomainValid(max) && (this.min < max);
     }
 
-    public checkMinMaxStep(step: number): boolean {
-        return this.isMinMaxValid && this.stepRefValue.intervalHasValue(step);
+    public checkMinMaxStep(step: number, force: boolean = false): boolean {
+        return this.computeMinMaxValidity(force) && this.stepRefValue.intervalHasValue(step);
+    }
+
+    get isValueValid(): boolean {
+        return this.computeValueValidity();
     }
 
     /**
      * Return true if single value is valid regarding the domain constraints
      */
-    get isValueValid(): boolean {
+    private computeValueValidity(force: boolean = false): boolean {
         try {
             const v = this.paramValues.singleValue;
-            this.checkValueAgainstDomain(v);
+            this.checkValueAgainstDomain(v, force);
             return true;
         } catch (e) {
             return false;
@@ -674,16 +678,24 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     }
 
     get isMinMaxValid(): boolean {
-        return this.checkMinMax(this.min, this.max);
+        return this.computeMinMaxValidity();
+    }
+
+    private computeMinMaxValidity(force: boolean = false): boolean {
+        return this.checkMinMax(this.min, this.max, force);
+    }
+
+    public get isRangeValid(): boolean {
+        return this.computeRangeValidity();
     }
 
     /**
      * Return true if current value is valid regarding the range constraints : min / max / step
      */
-    public get isRangeValid(): boolean {
+    private computeRangeValidity(force: boolean = false): boolean {
         switch (this.valueMode) {
             case ParamValueMode.LISTE:
-                return this.isListValid;
+                return this.computeListValidity(force);
 
             case ParamValueMode.MINMAX:
                 return this.checkMinMaxStep(this.step);
@@ -693,6 +705,10 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
             + `de ParamValueMode non prise en compte`);
     }
 
+    public get isValid(): boolean {
+        return this.computeValidity();
+    }
+
     /**
      * Root method to determine if a field value is valid, regarding the model constraints.
      *
@@ -706,14 +722,14 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
      *    - if it is not, checks the "computability" of the target Nub (ie. validity of the Nub) to allow
      *      triggering chain computation
      */
-    public get isValid(): boolean {
+    public computeValidity(force: boolean = false): boolean {
         switch (this.valueMode) {
             case ParamValueMode.SINGLE:
-                return this.isValueValid;
+                return this.computeValueValidity(force);
 
             case ParamValueMode.MINMAX:
             case ParamValueMode.LISTE:
-                return this.isRangeValid;
+                return this.computeRangeValidity(force);
 
             case ParamValueMode.CALCUL:
                 return true;
@@ -727,7 +743,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
                 if (iterator) {
                     try {
                         for (const v of iterator) {
-                            this.checkValueAgainstDomain(v);
+                            this.checkValueAgainstDomain(v, force);
                         }
                         return true;
                     } catch (e) {
@@ -735,7 +751,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
                     }
                 } else { // undefined iterator means target results are not computed yet
                     // check target Nub computability
-                    return this.referencedValue.nub.isComputable();
+                    return this.referencedValue.nub.isComputable(force);
                 }
         }
 
@@ -1223,7 +1239,13 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     public set allowInvalidValues(b: boolean) {
         const old = this._allowInvalidValues;
         this._allowInvalidValues = b;
-        if (old && !b && !this.isValid) {
+        if (old && !b) { // if _allowInvalidValues changed from true to false
+            this.checkValidity();
+        }
+    }
+
+    public checkValidity(force: boolean = false) {
+        if (!this.computeValidity(force)) {
             throw new Error("ParamDefinition : valeur non valide");
         }
     }
@@ -1240,13 +1262,13 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     /**
      * vérifie si un min/max est valide par rapport au domaine de définition
      */
-    private isMinMaxDomainValid(v: number): boolean {
+    private isMinMaxDomainValid(v: number, force: boolean = false): boolean {
         if (v === undefined) {
             return false;
         }
         if (this.valueMode === ParamValueMode.MINMAX) {
             try {
-                this.checkValueAgainstDomain(v);
+                this.checkValueAgainstDomain(v, force);
             } catch (e) {
                 return false;
             }
@@ -1254,18 +1276,18 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
         return true;
     }
 
-    private checkMinMax(min: number, max: number): boolean {
-        return this.isMinMaxDomainValid(min) && this.isMinMaxDomainValid(max) && (min < max);
+    private checkMinMax(min: number, max: number, force: boolean): boolean {
+        return this.isMinMaxDomainValid(min, force) && this.isMinMaxDomainValid(max, force) && (min < max);
     }
 
-    private get isListValid(): boolean {
+    private computeListValidity(force: boolean = false) {
         if (this.paramValues.valueList === undefined) {
             return false;
         }
 
         for (const v of this.paramValues.valueList) {
             try {
-                this.checkValueAgainstDomain(v);
+                this.checkValueAgainstDomain(v, force);
             } catch (e) {
                 return false;
             }