diff --git a/src/output/WriterBase.cpp b/src/output/WriterBase.cpp
index 83d890c2ab8bf31e60d7ed09e4e2da7770ebbfb8..b5cbee4c412d485fcdd12d6497e4b1fec20706f1 100644
--- a/src/output/WriterBase.cpp
+++ b/src/output/WriterBase.cpp
@@ -70,6 +70,63 @@ WriterBase::_checkConnectivity(
   }
 }
 
+void
+WriterBase::_checkSignature(
+  const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
+{
+  using NameTypeMap = std::map<std::string, std::string>;
+  NameTypeMap name_type_map;
+
+  for (auto named_discrete_data : named_discrete_data_list) {
+    switch (named_discrete_data->type()) {
+    case INamedDiscreteData::Type::item_value: {
+      const NamedItemValueVariant& named_item_value = dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data);
+      std::visit(
+        [&](auto&& item_value) {
+          using ItemValueT = std::decay_t<decltype(item_value)>;
+          using DataType   = std::decay_t<typename ItemValueT::data_type>;
+
+          std::ostringstream type_name;
+          type_name << "item_value(" << dataTypeName(ast_node_data_type_from<DataType>) << ')';
+
+          name_type_map[named_discrete_data->name()] = type_name.str();
+        },
+        named_item_value.itemValueVariant()->itemValue());
+      break;
+    }
+    case INamedDiscreteData::Type::discrete_function: {
+      const NamedDiscreteFunction& named_discrete_function =
+        dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data);
+      std::visit(
+        [&](auto&& discrete_function) {
+          std::ostringstream type_name;
+          type_name << "Vh(" << dataTypeName(discrete_function.dataType()) << ')';
+
+          name_type_map[named_discrete_data->name()] = type_name.str();
+        },
+        named_discrete_function.discreteFunctionVariant()->discreteFunction());
+      break;
+    }
+    default: {
+      throw UnexpectedError("unexpected discrete data type");
+    }
+    }
+  }
+
+  std::string signature{"|"};
+  for (auto&& [name, type_name] : name_type_map) {
+    signature += name + std::string{"-"} + type_name + std::string{"|"};
+  }
+
+  if (m_signature.has_value()) {
+    if (m_signature.value() != signature) {
+      throw NormalError("output variable list changed");
+    }
+  } else {
+    m_signature = signature;
+  }
+}
+
 void
 WriterBase::_checkMesh(const std::shared_ptr<const IMesh>& mesh,
                        const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
@@ -223,10 +280,10 @@ WriterBase::_getOutputNamedItemDataSet(
 }
 
 WriterBase::WriterBase(const std::string& base_filename, const double& time_period)
-  : m_base_filename{base_filename}, m_period_manager(time_period)
+  : m_base_filename{base_filename}, m_period_manager(time_period), m_signature(std::nullopt)
 {}
 
-WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename} {}
+WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename}, m_signature(std::nullopt) {}
 
 void
 WriterBase::write(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const
@@ -250,6 +307,7 @@ WriterBase::writeIfNeeded(const std::vector<std::shared_ptr<const INamedDiscrete
 
     if (time >= m_period_manager->nextTime()) {
       std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list);
+      this->_checkSignature(named_discrete_data_list);
       this->_writeAtTime(*mesh, named_discrete_data_list, time);
       m_period_manager->setSaveTime(time);
     }
@@ -265,7 +323,9 @@ WriterBase::writeForced(const std::vector<std::shared_ptr<const INamedDiscreteDa
   if (m_period_manager.has_value()) {
     if (time == m_period_manager->getLastTime())
       return;   // output already performed
+
     std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list);
+    this->_checkSignature(named_discrete_data_list);
     this->_writeAtTime(*mesh, named_discrete_data_list, time);
     m_period_manager->setSaveTime(time);
   } else {
diff --git a/src/output/WriterBase.hpp b/src/output/WriterBase.hpp
index 7fae994d78ed0e97be8f10d63097464280c739fc..707ac52d3a3c69c749c46047bd594b0be46c408b 100644
--- a/src/output/WriterBase.hpp
+++ b/src/output/WriterBase.hpp
@@ -85,7 +85,11 @@ class WriterBase : public IWriter
 
   std::optional<PeriodManager> m_period_manager;
 
+  mutable std::optional<std::string> m_signature;
+
  private:
+  void _checkSignature(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const;
+
   template <typename DiscreteFunctionType>
   static void _registerDiscreteFunction(const std::string& name, const DiscreteFunctionType&, OutputNamedItemDataSet&);