diff --git a/include/aidge/utils/ErrorHandling.hpp b/include/aidge/utils/ErrorHandling.hpp
index 8fbeff30abecfec0077786b21825b6a6f36677c6..f4a929867ec28e3e2fc9d0bdfedb6e6265c07adc 100644
--- a/include/aidge/utils/ErrorHandling.hpp
+++ b/include/aidge/utils/ErrorHandling.hpp
@@ -24,19 +24,9 @@
 do { std::printf(__VA_ARGS__); std::abort(); } while (false)
 #else
 #include <stdexcept>
-#include <memory>
+#include "aidge/utils/Formatting.hpp"
 #define AIDGE_THROW_OR_ABORT(ex, ...) \
-do { \
-    int n = 128; \
-    std::unique_ptr<char[]> formatted; \
-    formatted.reset(new char[n]); \
-    const int len = std::snprintf(formatted.get(), n, __VA_ARGS__); \
-    if (len >= n) { \
-        formatted.reset(new char[len + 1]); \
-        std::snprintf(formatted.get(), len + 1, __VA_ARGS__); \
-    }; \
-    throw ex(formatted.get()); \
-} while (false)
+throw ex(stringFormat(__VA_ARGS__))
 #endif
 
 /**
diff --git a/include/aidge/utils/Formatting.hpp b/include/aidge/utils/Formatting.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f572a86743004fe34395ddb6559ac36b5dc6634
--- /dev/null
+++ b/include/aidge/utils/Formatting.hpp
@@ -0,0 +1,63 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_FORMATTING_H_
+#define AIDGE_FORMATTING_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace Aidge {
+// The code snippet below is licensed under CC0 1.0.
+template<typename ... Args>
+std::string stringFormat(const std::string& format, Args... args) {
+// Disable security warning on GCC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-security"
+// Disable security warning on MSVC
+#pragma warning(push)
+#pragma warning(disable : 4774)
+    int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
+    if (size_s <= 0) {
+        std::printf("Error during formatting.");
+        std::abort();
+    }
+    auto size = static_cast<size_t>(size_s);
+    std::unique_ptr<char[]> buf(new char[size]);
+    std::snprintf(buf.get(), size, format.c_str(), args...);
+    return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
+#pragma warning(pop) 
+#pragma GCC diagnostic pop
+}
+
+/**
+ * Print any iterable object in a std::string.
+*/
+template <class T>
+std::string print(const T& vec, const std::string& format) {
+    std::string str = "{";
+    bool first = true;
+    for (const auto& val : vec) {
+        if (!first) {
+            str += ", ";
+        }
+        else {
+            first = false;
+        }
+        str += stringFormat(format, val);
+    }
+    str += "}";
+    return str;
+}
+}
+
+#endif //AIDGE_FORMATTING_H_
diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp
index 66421886f136ce77399b9bda54bc15fea91b0bc3..cb44faa9066b042047e2ab235ffd4d47cfaa0c14 100644
--- a/src/graph/GraphView.cpp
+++ b/src/graph/GraphView.cpp
@@ -334,7 +334,7 @@ void Aidge::GraphView::_forwardDims(std::set<std::shared_ptr<Node>> listNodes) {
     }
 
     // Internal check to make sure we won't enter in an infinite loop!
-    AIDGE_INTERNAL_ASSERT(nextList != listNodes);
+    AIDGE_ASSERT(nextList != listNodes, "Unable to forward dimensions (circular dependency and/or wrong dimensions?)");
 
     if (!nextList.empty()) {
         _forwardDims(nextList);
diff --git a/src/operator/Mul.cpp b/src/operator/Mul.cpp
index bc268263e8a6e2ec7c9944faa31da84dc50c4f53..fb82c1f750cee44eca2e63874f97c40e142e69dc 100644
--- a/src/operator/Mul.cpp
+++ b/src/operator/Mul.cpp
@@ -34,4 +34,7 @@ void Aidge::Mul_Op::computeOutputDims() {
     {
         mOutputs[0]->resize(getInput(0)->dims());
     }
+    else if (!getInput(0)->empty() && !getInput(1)->empty()) {
+        AIDGE_THROW_OR_ABORT(std::runtime_error, "Incompatible input dimensions for Operator Mul");
+    }
 }
\ No newline at end of file
diff --git a/src/operator/Operator.cpp b/src/operator/Operator.cpp
index 4adc57f55f7531c28c0c0603ee01c176bdd59e96..32f17238584eac07bd33eed57b3f28528d61a5b3 100644
--- a/src/operator/Operator.cpp
+++ b/src/operator/Operator.cpp
@@ -32,17 +32,21 @@ Aidge::Operator::~Operator() noexcept = default;
 ///////////////////////////////////////////////////////
 
 Aidge::NbElts_t Aidge::Operator::getNbRequiredData(const Aidge::IOIndex_t inputIdx) const {
+    AIDGE_ASSERT(mImpl != nullptr, "getNbRequiredData(): an implementation is required!");
     return mImpl->getNbRequiredData(inputIdx);
 }
 
 Aidge::NbElts_t Aidge::Operator::getNbConsumedData(Aidge::IOIndex_t inputIdx) const {
+    AIDGE_ASSERT(mImpl != nullptr, "getNbConsumedData(): an implementation is required!");
     return mImpl->getNbConsumedData(inputIdx);
 }
 
 Aidge::NbElts_t Aidge::Operator::getNbProducedData(Aidge::IOIndex_t outputIdx) const {
+    AIDGE_ASSERT(mImpl != nullptr, "getNbProducedData(): an implementation is required!");
     return mImpl->getNbProducedData(outputIdx);
 }
 void Aidge::Operator::updateConsummerProducer(){
+    AIDGE_ASSERT(mImpl != nullptr, "updateConsummerProducer(): an implementation is required!");
     mImpl->updateConsummerProducer();
 }
 
@@ -52,12 +56,9 @@ void Aidge::Operator::runHooks() const {
     }
 }
 void Aidge::Operator::forward() {
-    if(mImpl) {
-        mImpl->forward();
-        runHooks();
-    } else {
-        printf("forward: No implementation is linked.\n");
-    }
+    AIDGE_ASSERT(mImpl != nullptr, "forward(): an implementation is required!");
+    mImpl->forward();
+    runHooks();
 }
 
 void Aidge::Operator::backward() { mImpl->backward(); }