diff --git a/Applications/ApplicationsLib/TestDefinition.cpp b/Applications/ApplicationsLib/TestDefinition.cpp
index 0611ac75736c2cb1a9c6903860ea378d3a026651..e51560b38b7313c585dfc13ef35c884e745cb96c 100644
--- a/Applications/ApplicationsLib/TestDefinition.cpp
+++ b/Applications/ApplicationsLib/TestDefinition.cpp
@@ -23,21 +23,32 @@
 
 namespace
 {
-/// Safe conversion of a double to a string using decimal or decimal exponent
-/// notation. See std::snprintf() for details for "%g" conversion specifier.
-/// \note std::to_string uses "%f" conversion specifier which is not sufficient
-/// for small numbers like 1e-15.
-std::string convert_to_string(double const& value)
+/// Test if the given string is convertible to a valid double value, not a NaN.
+bool isConvertibleToDouble(std::string const& s)
 {
-    // TODO (naumov) Replace this with fmt library.
-    char buffer[32];
-    int const chars_written =
-        std::snprintf(buffer, sizeof(buffer), "%g", value);
-    if (chars_written < 0 || chars_written >= static_cast<int>(sizeof(buffer)))
+    std::size_t pos = 0;
+    double value;
+    try
     {
-        OGS_FATAL("Could not convert a value to string.");
+        value = std::stod(s, &pos);
     }
-    return std::string{buffer};
+    catch (...)
+    {
+        OGS_FATAL("The given string '%s' is not convertible to double.",
+                  s.c_str());
+    }
+    if (pos != s.size())
+    {
+        OGS_FATAL(
+            "Only %d characters were used for double conversion of string '%s'",
+            pos, s.c_str());
+    }
+
+    if (std::isnan(value))
+    {
+        OGS_FATAL("The given string '%s' results in a NaN value.", s.c_str());
+    }
+    return true;
 }
 
 /// Wraps a string into double ticks.
@@ -172,23 +183,35 @@ TestDefinition::TestDefinition(BaseLib::ConfigTree const& config_tree,
         std::string const& reference_filename =
             BaseLib::joinPaths(reference_path, filename);
 
-        auto const& absolute_tolerance =
+        auto const absolute_tolerance =
             //! \ogs_file_param{prj__test_definition__vtkdiff__absolute_tolerance}
-            vtkdiff_config.getConfigParameterOptional<double>(
-                "absolute_tolerance");
+            vtkdiff_config.getConfigParameter<std::string>("absolute_tolerance",
+                                                           "");
+        if (!absolute_tolerance.empty() &&
+            !isConvertibleToDouble(absolute_tolerance))
+        {
+            OGS_FATAL(
+                "The absolute tolerance value '%s' is not convertible to "
+                "double.",
+                absolute_tolerance.c_str());
+        }
         std::string const absolute_tolerance_parameter =
-            absolute_tolerance == boost::none
-                ? ""
-                : "--abs " + convert_to_string(*absolute_tolerance);
+            "--abs " + absolute_tolerance;
 
-        auto const& relative_tolerance =
+        auto const relative_tolerance =
             //! \ogs_file_param{prj__test_definition__vtkdiff__relative_tolerance}
-            vtkdiff_config.getConfigParameterOptional<double>(
-                "relative_tolerance");
+            vtkdiff_config.getConfigParameter<std::string>("relative_tolerance",
+                                                           "");
+        if (!relative_tolerance.empty() &&
+            !isConvertibleToDouble(relative_tolerance))
+        {
+            OGS_FATAL(
+                "The relative tolerance value '%s' is not convertible to "
+                "double.",
+                relative_tolerance.c_str());
+        }
         std::string const relative_tolerance_parameter =
-            relative_tolerance == boost::none
-                ? ""
-                : "--rel " + convert_to_string(*relative_tolerance);
+            "--rel " + relative_tolerance;
 
         //
         // Construct command line.