diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index e37836d0f..af6769d8e 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -1236,8 +1236,8 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree( if(sub->instance_name == subtree_path) { throw RuntimeError("Duplicate SubTree path detected: '", subtree_path, - "'. Multiple SubTree nodes with the same 'name' attribute " - "under the same parent are not allowed. " + "'. SubTree nodes in the same tree cannot share a 'name' " + "attribute, even under different parent nodes. " "Please use unique names or omit the 'name' attribute " "to auto-generate unique paths."); } diff --git a/tests/gtest_subtree.cpp b/tests/gtest_subtree.cpp index 82a0a23bb..cce6fa372 100644 --- a/tests/gtest_subtree.cpp +++ b/tests/gtest_subtree.cpp @@ -815,7 +815,7 @@ TEST(SubTree, SubstringTreeIDsAreNotRecursive) // Test for Groot2 issue #56: duplicate _fullpath when multiple subtrees have the same name // https://github.com/BehaviorTree/Groot2/issues/56 // -// When two SubTree nodes under the same parent have the same "name" attribute, +// When two SubTree nodes in the same tree have the same "name" attribute, // tree creation should fail with a clear error message. TEST(SubTree, DuplicateSubTreeName_Groot2Issue56) { @@ -879,6 +879,48 @@ TEST(SubTree, DuplicateSubTreeName_ErrorMessage) } } +// The duplicate check covers the whole tree, so the message must not suggest +// that moving one SubTree under another parent fixes it. +TEST(SubTree, DuplicateSubTreeName_DifferentParents) +{ + // clang-format off + static const char* xml_text = R"( + + + + + + + + + + + + + + + + +)"; + // clang-format on + + BehaviorTreeFactory factory; + + try + { + (void)factory.createTreeFromText(xml_text); + FAIL() << "Expected RuntimeError to be thrown"; + } + catch(const RuntimeError& e) + { + std::string msg = e.what(); + EXPECT_TRUE(msg.find("Duplicate SubTree path") != std::string::npos) + << "Error message should mention 'Duplicate SubTree path'. Got: " << msg; + EXPECT_TRUE(msg.find("same parent") == std::string::npos) + << "Error message should not limit the rule to one parent. Got: " << msg; + } +} + // Test that unique names under the same parent work correctly TEST(SubTree, UniqueSubTreeNames_WorksCorrectly) {