#344 describes this as a known gap. This issue provides a concrete MRE and documents the full set of obstacles.
The natural ROS 2 pattern for launching a node:
launch_ros.actions.Node(package="my_pkg", executable="my_node")
does not work for Bazel-built nodes. They are never installed into an ament prefix, so ROS 2's libexec lookup (<prefix>/lib/my_pkg/my_node) always fails.
What doesn't work
import launch_ros.actions
from launch import LaunchDescription
def generate_launch_description():
# This is how you'd naturally write it -- but it fails under Bazel because
# `eg_talker` and `eg_listener` are not installed in any ament prefix.
return LaunchDescription(
[
launch_ros.actions.Node(
package="ros2_example_apps",
executable="eg_talker",
),
launch_ros.actions.Node(
package="ros2_example_apps",
executable="eg_listener",
),
]
)
ros_launch(
name = "roslaunch_eg_node_problem",
data = [
":eg_listener",
":eg_talker",
],
launch_file = "eg_launch_node_problem.py",
workspace_name = ros2_example_bazel_installed,
)
A workaround
import launch_ros.actions
from launch import LaunchDescription
from python.runfiles import runfiles
def generate_launch_description():
r = runfiles.Create()
prefix = "ros2_example_bazel_installed/ros2_example_apps"
return LaunchDescription(
[
launch_ros.actions.Node(
executable=r.Rlocation(f"{prefix}/eg_talker", source_repo=""),
),
launch_ros.actions.Node(
executable=r.Rlocation(f"{prefix}/eg_listener", source_repo=""),
),
]
)
What it would be good to have
- No hardcoded runfiles path strings in launch files
- Build-time validation that referenced executables exist
source_repo="" handled transparently, not by the user
Also, the source_repo requirement is a current bug of the current launch file support:
bazel run //ros2_example_apps:roslaunch_eg_py
.
.
.
[INFO] [launch]: All log files can be found below /home/frn/.ros/log/2026-04-07-15-28-43-711973-vader-2564850
[INFO] [launch]: Default logging verbosity is set to INFO
[ERROR] [launch]: Caught exception in launch (see debug for traceback): Caught multiple exceptions when trying to load file of format [py]:
- ValueError: /home/frn/drake-ros/ros2_example_bazel_installed/ros2_example_apps/eg_launch.py does not lie under the runfiles root /home/frn/.cache/bazel/_bazel_frn/a779afcb46037298559646c7c2f921d4/execroot/_main/bazel-out/k8-fastbuild/bin/ros2_example_apps/roslaunch_eg_py.runfiles
- InvalidFrontendLaunchFileError: The launch file may have a syntax error, or its format is unknown
#344 describes this as a known gap. This issue provides a concrete MRE and documents the full set of obstacles.
The natural ROS 2 pattern for launching a node:
does not work for Bazel-built nodes. They are never installed into an ament prefix, so ROS 2's libexec lookup (
<prefix>/lib/my_pkg/my_node) always fails.What doesn't work
A workaround
What it would be good to have
source_repo=""handled transparently, not by the userAlso, the
source_reporequirement is a current bug of the current launch file support: