Skip to content

C++ Recorder fails on stop() -> record() due to reusing bag name #2209

@trevor-luum

Description

@trevor-luum

Description

The C++ Recorder requires a bag URI to be provided in its node options or storage options, and will use that URI unmodified on every call to record(). This means that calling stop(), then calling record(), will throw a std::runtime_error due to reuse of the bag URI.

Expected Behavior

When calling record() after stop() on rosbag2_transport::Recorder, the Recorder will open a new bag.

Actual Behavior

The Recorder attempts to overwrite the existing bag, causing its internal Writer to throw runtime_error. Full program output is as follows:

[INFO] [1760127407.307654961] [rosbag2_recorder]: Press SPACE for pausing/resuming
[INFO] [1760127407.309737602] [rosbag2_recorder]: Listening for topics...
[INFO] [1760127407.309764815] [rosbag2_recorder]: Event publisher thread: Starting
[INFO] [1760127407.309827691] [rosbag2_recorder]: Recording...
[INFO] [1760127407.310978639] [rosbag2_recorder]: Pausing recording.
[INFO] [1760127407.311004204] [rosbag2_cpp]: Writing remaining messages from cache to the bag. It may take a while
[INFO] [1760127407.311383593] [rosbag2_recorder]: Event publisher thread: Exiting
[INFO] [1760127407.311432138] [rosbag2_recorder]: Recording stopped
terminate called after throwing an instance of 'std::runtime_error'
  what():  Bag directory already exists (foo), can't overwrite existing bag
Stack trace (most recent call last):
#14   Object "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", at 0xffffffffffffffff, in 
#13   Object "/home/trevor/Code/ros_ws/install/recorder/lib/recorder/recorder", at 0x6255d1e4ad24, in _start
#12   Source "../csu/libc-start.c", line 360, in __libc_start_main_impl [0x7f4e21e2a28a]
#11   Source "../sysdeps/nptl/libc_start_call_main.h", line 58, in __libc_start_call_main [0x7f4e21e2a1c9]
#10   Object "/home/trevor/Code/ros_ws/install/recorder/lib/recorder/recorder", at 0x6255d1e4b242, in main
#9    Object "/opt/ros/jazzy/lib/librosbag2_transport.so", at 0x7f4e22a01622, in rosbag2_transport::RecorderImpl::record()
#8    Object "/opt/ros/jazzy/lib/librosbag2_cpp.so", at 0x7f4e22116ad2, in rosbag2_cpp::Writer::open(rosbag2_storage::StorageOptions const&, rosbag2_cpp::ConverterOptions const&)
#7    Object "/opt/ros/jazzy/lib/librosbag2_cpp.so", at 0x7f4e22124b19, in rosbag2_cpp::writers::SequentialWriter::open(rosbag2_storage::StorageOptions const&, rosbag2_cpp::ConverterOptions const&)
#6    Source "../../../../src/libstdc++-v3/libsupc++/eh_throw.cc", line 98, in __cxa_throw [0x7f4e222bb390]
#5    Source "../../../../src/libstdc++-v3/libsupc++/eh_terminate.cc", line 58, in terminate [0x7f4e222a5a54]
#4    Source "../../../../src/libstdc++-v3/libsupc++/eh_terminate.cc", line 48, in __terminate [0x7f4e222bb0d9]
#3    Source "../../../../src/libstdc++-v3/libsupc++/vterminate.cc", line 95, in __verbose_terminate_handler [0x7f4e222a5ff4]
#2    Source "./stdlib/abort.c", line 79, in abort [0x7f4e21e288fe]
#1    Source "../sysdeps/posix/raise.c", line 26, in raise [0x7f4e21e4527d]
#0  | Source "./nptl/pthread_kill.c", line 89, in __pthread_kill_internal
    | Source "./nptl/pthread_kill.c", line 78, in __pthread_kill_implementation
      Source "./nptl/pthread_kill.c", line 44, in __pthread_kill [0x7f4e21e9eb2c]
Aborted (Signal sent by tkill() 1639237 1001)
[ros2run]: Aborted

To Reproduce

The above error was produced by running the following:

int main(int argc, char* argv[]) {
  rclcpp::init(argc, argv);

  rclcpp::executors::SingleThreadedExecutor exec;

  rclcpp::NodeOptions options;
  options.parameter_overrides({{"storage.uri", "foo"}});

  auto bagRecorder = std::make_shared<rosbag2_transport::Recorder>(options);
  exec.add_node(bagRecorder);

  bagRecorder->stop();
  bagRecorder->record();

  exec.spin();

  rclcpp::shutdown();

  return 0;
}

System (please complete the following information)

  • OS: Ubuntu noble
  • ROS 2 Distro: Jazzy
  • Install Method: apt
  • Version: 0.26.9-1noble.20250912.132555

Additional context

This is missed by RecordIntegrationTestFixture.can_record_again_after_stop since that test uses MockSequentialWriter, which doesn't check for repeat URIs in its open() method.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions