diff --git a/include/behaviortree_cpp/actions/set_blackboard_node.h b/include/behaviortree_cpp/actions/set_blackboard_node.h
index 9882cea6f..1a240c3db 100644
--- a/include/behaviortree_cpp/actions/set_blackboard_node.h
+++ b/include/behaviortree_cpp/actions/set_blackboard_node.h
@@ -61,13 +61,16 @@ class SetBlackboardNode : public SyncActionNode
     const std::string value_str = config().input_ports.at("value");
 
     StringView stripped_key;
+    BT::Any out_value;
+
+    std::shared_ptr<Blackboard::Entry> dst_entry =
+        config().blackboard->getEntry(output_key);
+
     if(isBlackboardPointer(value_str, &stripped_key))
     {
       const auto input_key = std::string(stripped_key);
       std::shared_ptr<Blackboard::Entry> src_entry =
           config().blackboard->getEntry(input_key);
-      std::shared_ptr<Blackboard::Entry> dst_entry =
-          config().blackboard->getEntry(output_key);
 
       if(!src_entry)
       {
@@ -78,13 +81,35 @@ class SetBlackboardNode : public SyncActionNode
         config().blackboard->createEntry(output_key, src_entry->info);
         dst_entry = config().blackboard->getEntry(output_key);
       }
-      dst_entry->value = src_entry->value;
+
+      out_value = src_entry->value;
     }
     else
     {
-      config().blackboard->set(output_key, value_str);
+      out_value = BT::Any(value_str);
+    }
+
+    if(out_value.empty())
+      return NodeStatus::FAILURE;
+
+    // avoid type issues when port is remapped: current implementation of the set might be a little bit problematic for initialized on the fly values
+    // this still does not attack math issues
+    if(dst_entry && dst_entry->info.type() != typeid(std::string) && out_value.isString())
+    {
+      try
+      {
+        out_value = dst_entry->info.parseString(out_value.cast<std::string>());
+      }
+      catch(const std::exception& e)
+      {
+        throw LogicError("Can't convert string [", out_value.cast<std::string>(),
+                         "] to type [", BT::demangle(dst_entry->info.type()),
+                         "]: ", e.what());
+      }
     }
 
+    config().blackboard->set(output_key, out_value);
+
     return NodeStatus::SUCCESS;
   }
 };
diff --git a/tests/gtest_blackboard.cpp b/tests/gtest_blackboard.cpp
index fcbc272a3..35be37dab 100644
--- a/tests/gtest_blackboard.cpp
+++ b/tests/gtest_blackboard.cpp
@@ -458,6 +458,29 @@ struct Point
   double y;
 };
 
+// Template specialization to converts a string to Point.
+namespace BT
+{
+template <>
+[[nodiscard]] Point convertFromString(StringView str)
+{
+  // We expect real numbers separated by semicolons
+  auto parts = splitString(str, ';');
+  if(parts.size() != 2)
+  {
+    throw RuntimeError("invalid input)");
+  }
+  else
+  {
+    Point output{ 0.0, 0.0 };
+    output.x = convertFromString<double>(parts[0]);
+    output.y = convertFromString<double>(parts[1]);
+    // std::cout << "Building a position 2d object " << output.x << "; " << output.y << "\n" << std::flush;
+    return output;
+  }
+}
+}  // end namespace BT
+
 TEST(BlackboardTest, SetBlackboard_Issue725)
 {
   BT::BehaviorTreeFactory factory;
@@ -654,3 +677,180 @@ TEST(BlackboardTest, TimestampedInterface)
   ASSERT_EQ(stamp_opt->seq, 2);
   ASSERT_GE(stamp_opt->time.count(), nsec_before);
 }
+
+TEST(BlackboardTest, SetBlackboard_Upd_Ts_SeqId)
+{
+  BT::BehaviorTreeFactory factory;
+
+  const std::string xml_text = R"(
+  <root BTCPP_format="4">
+    <BehaviorTree ID="MainTree">
+      <Sequence>
+        <Script code="other_point:=first_point" />
+        <Sleep msec="5" />
+        <SetBlackboard value="{second_point}" output_key="other_point" />
+      </Sequence>
+    </BehaviorTree>
+  </root> )";
+
+  factory.registerBehaviorTreeFromText(xml_text);
+  auto tree = factory.createTree("MainTree");
+  auto& blackboard = tree.subtrees.front()->blackboard;
+
+  const Point point1 = { 2, 2 };
+  const Point point2 = { 3, 3 };
+  blackboard->set("first_point", point1);
+  blackboard->set("second_point", point2);
+
+  tree.tickExactlyOnce();
+  const auto entry_ptr = blackboard->getEntry("other_point");
+  const auto ts1 = entry_ptr->stamp;
+  const auto seq_id1 = entry_ptr->sequence_id;
+  tree.tickWhileRunning();
+  const auto ts2 = entry_ptr->stamp;
+  const auto seq_id2 = entry_ptr->sequence_id;
+
+  ASSERT_GT(ts2.count(), ts1.count());
+  ASSERT_GT(seq_id2, seq_id1);
+}
+
+TEST(BlackboardTest, SetBlackboard_ChangeType1)
+{
+  BT::BehaviorTreeFactory factory;
+
+  const std::string xml_text = R"(
+  <root BTCPP_format="4">
+    <BehaviorTree ID="MainTree">
+      <Sequence>
+        <SetBlackboard value="{first_point}" output_key="other_point" />
+        <Sleep msec="5" />
+        <SetBlackboard value="{random_str}" output_key="other_point" />
+      </Sequence>
+    </BehaviorTree>
+  </root> )";
+
+  factory.registerBehaviorTreeFromText(xml_text);
+  auto tree = factory.createTree("MainTree");
+  auto& blackboard = tree.subtrees.front()->blackboard;
+
+  const Point point = { 2, 7 };
+  blackboard->set("first_point", point);
+  blackboard->set("random_str", "Hello!");
+
+  // First tick should succeed
+  ASSERT_NO_THROW(tree.tickExactlyOnce());
+  const auto entry_ptr = blackboard->getEntry("other_point");
+  std::this_thread::sleep_for(std::chrono::milliseconds{ 5 });
+  // Second tick should throw due to type mismatch
+  EXPECT_THROW({ tree.tickWhileRunning(); }, BT::LogicError);
+}
+
+TEST(BlackboardTest, SetBlackboard_ChangeType2)
+{
+  BT::BehaviorTreeFactory factory;
+
+  const std::string xml_text = R"(
+  <root BTCPP_format="4">
+    <BehaviorTree ID="MainTree">
+      <Sequence>
+        <SetBlackboard value="{first_point}" output_key="other_point" />
+        <Sleep msec="5" />
+        <SetBlackboard value="{random_num}" output_key="other_point" />
+      </Sequence>
+    </BehaviorTree>
+  </root> )";
+
+  factory.registerBehaviorTreeFromText(xml_text);
+  auto tree = factory.createTree("MainTree");
+  auto& blackboard = tree.subtrees.front()->blackboard;
+
+  const Point point = { 2, 7 };
+  blackboard->set("first_point", point);
+  blackboard->set("random_num", 57);
+
+  // First tick should succeed
+  ASSERT_NO_THROW(tree.tickExactlyOnce());
+  const auto entry_ptr = blackboard->getEntry("other_point");
+  std::this_thread::sleep_for(std::chrono::milliseconds{ 5 });
+  // Second tick should throw due to type mismatch
+  EXPECT_THROW({ tree.tickWhileRunning(); }, BT::LogicError);
+}
+
+// Simple Action that updates an instance of Point in the blackboard
+class UpdatePosition : public BT::SyncActionNode
+{
+public:
+  UpdatePosition(const std::string& name, const BT::NodeConfig& config)
+    : BT::SyncActionNode(name, config)
+  {}
+
+  BT::NodeStatus tick() override
+  {
+    const auto in_pos = getInput<Point>("pos_in");
+    if(!in_pos.has_value())
+      return BT::NodeStatus::FAILURE;
+    Point _pos = in_pos.value();
+    _pos.x += getInput<double>("x").value_or(0.0);
+    _pos.y += getInput<double>("y").value_or(0.0);
+    setOutput("pos_out", _pos);
+    return BT::NodeStatus::SUCCESS;
+  }
+
+  static BT::PortsList providedPorts()
+  {
+    return { BT::InputPort<Point>("pos_in", { 0.0, 0.0 }, "Initial position"),
+             BT::InputPort<double>("x"), BT::InputPort<double>("y"),
+             BT::OutputPort<Point>("pos_out") };
+  }
+
+private:
+};
+
+TEST(BlackboardTest, SetBlackboard_WithPortRemapping)
+{
+  BT::BehaviorTreeFactory factory;
+
+  const std::string xml_text = R"(
+    <?xml version="1.0"?>
+    <root BTCPP_format="4" main_tree_to_execute="MainTree">
+      <BehaviorTree ID="MainTree">
+          <Sequence>
+              <SetBlackboard output_key="pos" value="0.0;0.0" />
+              <Repeat num_cycles="3">
+                  <Sequence>
+                      <UpdatePosition pos_in="{pos}" x="0.1" y="0.2" pos_out="{pos}"/>
+                      <SubTree ID="UpdPosPlus" _autoremap="true" new_pos="2.2;2.4" />
+                      <Sleep msec="125"/>
+                      <SetBlackboard output_key="pos" value="22.0;22.0" />
+                  </Sequence>
+              </Repeat>
+          </Sequence>
+      </BehaviorTree>
+      <BehaviorTree ID="UpdPosPlus">
+          <Sequence>
+              <SetBlackboard output_key="pos" value="3.0;5.0" />
+              <SetBlackboard output_key="pos" value="{new_pos}" />
+          </Sequence>
+      </BehaviorTree>
+    </root>
+  )";
+
+  factory.registerNodeType<UpdatePosition>("UpdatePosition");
+  factory.registerBehaviorTreeFromText(xml_text);
+  auto tree = factory.createTree("MainTree");
+  auto& blackboard = tree.subtrees.front()->blackboard;
+
+  // First tick should succeed and update the value within the subtree
+  ASSERT_NO_THROW(tree.tickExactlyOnce());
+
+  const auto entry_ptr = blackboard->getEntry("pos");
+  ASSERT_EQ(entry_ptr->value.type(), typeid(Point));
+
+  const auto x = entry_ptr->value.cast<Point>().x;
+  const auto y = entry_ptr->value.cast<Point>().y;
+  ASSERT_EQ(x, 2.2);
+  ASSERT_EQ(y, 2.4);
+
+  // Tick till the end with no crashes
+  ASSERT_NO_THROW(tree.tickWhileRunning(););
+}