diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 478e9df8d818dd24443624276df0f5c89ac18553..247bbad092dc801126fcfe84268e18b1331fd39e 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -4245,7 +4245,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
     {
       auto contemporaneous_jacobian = evaluateAndReduceJacobian(eval_context);
 
-      computeNonSingularNormalization(contemporaneous_jacobian);
+      computeNonSingularNormalization(contemporaneous_jacobian, true);
 
       auto [prologue, epilogue] = computePrologueAndEpilogue();
 
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 37319bacd3b24c580ef6aa7a69148c7ed1ee5d86..a78a57b767cc87449aadf284d65a7676377a3be3 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -201,7 +201,7 @@ ModelTree::operator=(const ModelTree &m)
 }
 
 bool
-ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose)
+ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic, bool verbose)
 {
   const int n = equations.size();
 
@@ -241,7 +241,7 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, boo
       it != mate_map.begin() + n)
     {
       if (verbose)
-        cerr << "ERROR: Could not normalize the model. Variable "
+        cerr << "ERROR: Could not normalize the " << (dynamic ? "dynamic" : "static") << " model. Variable "
              << symbol_table.getName(symbol_table.getID(SymbolType::endogenous, it - mate_map.begin()))
              << " is not in the maximum cardinality matching." << endl;
       check = false;
@@ -250,9 +250,9 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, boo
 }
 
 void
-ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian)
+ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic)
 {
-  cout << "Normalizing the model..." << endl;
+  cout << "Normalizing the " << (dynamic ? "dynamic" : "static") << " model..." << endl;
 
   int n = equations.size();
 
@@ -284,14 +284,14 @@ ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_ja
           suppressed++;
 
       if (suppressed != last_suppressed)
-        found_normalization = computeNormalization(normalized_contemporaneous_jacobian_above_cutoff, false);
+        found_normalization = computeNormalization(normalized_contemporaneous_jacobian_above_cutoff, dynamic, false);
       last_suppressed = suppressed;
       if (!found_normalization)
         {
           current_cutoff /= 2;
           // In this last case try to normalize with the complete jacobian
           if (current_cutoff <= cutoff_lower_limit)
-            found_normalization = computeNormalization(normalized_contemporaneous_jacobian, false);
+            found_normalization = computeNormalization(normalized_contemporaneous_jacobian, dynamic, false);
         }
     }
 
@@ -302,12 +302,19 @@ ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_ja
          normalization even with a potential singularity.
          TODO: Explain why symbolic_jacobian is not contemporaneous. */
       auto symbolic_jacobian = computeSymbolicJacobian();
-      found_normalization = computeNormalization(symbolic_jacobian, true);
+      found_normalization = computeNormalization(symbolic_jacobian, dynamic, true);
     }
 
   if (!found_normalization)
     {
-      cerr << "No normalization could be computed. Aborting." << endl;
+      /* Some models don’t have a steady state, and this can cause the
+         normalization to fail (e.g. if some variable only appears in a diff(),
+         it will disappear from the static model). Suggest the “no_static”
+         option as a possible solution. */
+      if (!dynamic)
+        cerr << "If your model does not have a steady state, you may want to try the 'no_static' option of the 'model' block." << endl;
+      /* The last call to computeNormalization(), which was verbose, already
+         printed an error message, so we can immediately exit. */
       exit(EXIT_FAILURE);
     }
 }
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 4c5b18102478e6373efc72b1dc06b2567532819d..c7f17aeaeae05563bdf8e7daeaac8104d105c1cc 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -283,7 +283,7 @@ protected:
     \param contemporaneous_jacobian Jacobian used as an incidence matrix: all elements declared in the map (even if they are zero), are used as vertices of the incidence matrix
     \return True if a complete normalization has been achieved
   */
-  bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose);
+  bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic, bool verbose);
 
   //! Try to compute the matching between endogenous and variable using a decreasing cutoff
   /*!
@@ -292,7 +292,7 @@ protected:
     If no matching is found with a zero cutoff, an error message is printed.
     The resulting normalization is stored in endo2eq.
   */
-  void computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian);
+  void computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic);
   //! Evaluate the jacobian (w.r.t. endogenous) and suppress all the elements below the cutoff
   /*! Returns the contemporaneous_jacobian.
       Elements below the cutoff are discarded. External functions are evaluated to 1. */
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 906bdca0d7ec919f152bd8be5cadf16940f83214..3123b088bfe0dd06cdd590bd59f9ab94d6509cda 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2021 Dynare Team
+ * Copyright © 2003-2022 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -1040,7 +1040,7 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
     {
       auto contemporaneous_jacobian = evaluateAndReduceJacobian(eval_context);
 
-      computeNonSingularNormalization(contemporaneous_jacobian);
+      computeNonSingularNormalization(contemporaneous_jacobian, false);
 
       auto [prologue, epilogue] = computePrologueAndEpilogue();