Skip to main content

Troubleshooting

A systematic checklist for the ROS 2 problems you will run into most often: missing topics, type mismatches, QoS incompatibilities, Domain ID conflicts, DDS discovery issues, container networking, timestamp/clock problems, TF errors, and permissions. Each section gives the commands to confirm (or rule out) that cause before moving to the next.

Overview​

Most ROS 2 issues fall into a small number of categories, and most of them are diagnosable from the command line in under a minute once you know where to look. Work through the relevant section below in order — top to bottom within a section — rather than guessing.

Why It Matters​

"It doesn't work" is not actionable. A short, repeatable diagnostic sequence turns a vague symptom into a specific, fixable cause, and is faster than trial-and-error changes to code or configuration.

Missing Topics​

A node, topic, service, or action you expect to see does not appear anywhere.

  1. Confirm the environment is sourced in the terminal you are checking from:
    printenv ROS_DISTRO
    which ros2
    See CLI Basics.
  2. Confirm the node is actually running (not crashed on startup):
    ros2 node list
    If it's missing, check the terminal that launched it for a stack trace or error.
  3. Confirm ROS_DOMAIN_ID matches between the terminal running the node and the terminal running the CLI — see Domain ID below.
  4. Confirm the fully resolved topic name and namespace:
    ros2 topic list
    A relative topic name used in code may resolve to a different fully qualified name depending on the node's namespace.
  5. Check for a QoS mismatch if the topic is listed but echo shows nothing — see QoS Mismatch below.

Type Mismatch​

Two nodes appear to use the "same" topic or service name but cannot exchange data, or a CLI call reports a type error.

ros2 topic type /some_topic
ros2 interface show <package>/msg/<Type>
  • The package name and type name must match exactly on both ends (e.g., std_msgs/msg/String vs. a custom message with the same field names is not the same type).
  • If you built a custom interface package, confirm it was rebuilt and the overlay re-sourced after any .msg/.srv/.action file change — stale generated code is a common cause of "it used to work."
  • For services/actions, check the request/response or goal/result/feedback shape with ros2 interface show, and compare field-by-field with what the client is sending.

QoS Mismatch​

A publisher and subscriber both exist on the same topic, but no data flows between them.

ros2 topic info /some_topic -v

This prints the QoS profile (reliability, durability, history, depth) for every publisher and subscriber on the topic. Common incompatibilities:

SettingMismatch that breaks delivery
ReliabilityPublisher BEST_EFFORT with subscriber RELIABLE (subscriber requests a guarantee the publisher does not offer)
DurabilityPublisher VOLATILE with subscriber TRANSIENT_LOCAL (subscriber expects late-joining delivery of the last message; publisher does not keep one)

The fix is to make the publisher and subscriber QoS profiles compatible. They do not need to be identical; the publisher must offer QoS guarantees that satisfy the subscriber's requested profile.

Domain ID​

Nodes that should see each other do not, even on the same network, with no other obvious cause.

printenv ROS_DOMAIN_ID
  • Nodes that should participate in the same ROS 2 DDS domain normally need the same ROS_DOMAIN_ID (default 0 if unset). Matching the Domain ID is necessary for ordinary discovery, but it does not guarantee communication if network, middleware, firewall, or discovery settings are incompatible.
  • Advantech Robotic Suite provides a helper script for changing it consistently; see ROS 2 Domain ID.
  • Check both the host and any container shells independently — sourcing a container does not guarantee it inherited the host's environment variable.

DDS Discovery​

Nodes are on the same Domain ID but still cannot see each other, especially across machines or over Wi-Fi/VPN links.

  • Multicast-based discovery (the default for most RMW/DDS implementations) can be blocked by network configuration, firewalls, or certain virtual/VPN network adapters. Confirm basic connectivity first (e.g., ping) between the machines involved.
  • Check which RMW implementation is active — this changes discovery behavior and available tuning options:
    printenv RMW_IMPLEMENTATION
  • ros2 doctor runs several baseline environment and network checks and is a reasonable first step:
    ros2 doctor --report
  • When nodes are split across multiple machines, confirm firewall rules allow the DDS traffic (ports and protocol depend on the RMW implementation in use — check that implementation's documentation rather than assuming a specific port range applies universally).

Containers​

Advantech Robotic Suite runs ROS 2 inside containers on some platforms; container boundaries introduce their own discovery and environment pitfalls.

  • Confirm the container's network mode allows the DDS discovery traffic it needs (host networking is the simplest configuration for local discovery; bridged networking often requires extra configuration).
  • Environment variables (ROS_DOMAIN_ID, RMW_IMPLEMENTATION) set on the host are not automatically visible inside a container unless explicitly passed through or re-sourced inside the container shell — check both sides independently:
    docker exec -it <container_name> bash -c 'printenv ROS_DOMAIN_ID'
  • If a node inside a container cannot see a node on the host (or in a different container), first confirm they use the same Domain ID and network mode before investigating anything more complex.

Timestamps and Clock​

Time-dependent behavior (TF lookups, message filtering, synchronized playback) misbehaves.

  • Confirm whether the nodes involved expect simulated time. If use_sim_time is true on a node but nothing publishes /clock, that node's clock will not advance as expected. See Rosbag.
  • Confirm system clocks are reasonably synchronized across machines if timestamps are compared across a distributed system — large clock skew produces symptoms that look like TF or QoS bugs.
  • For "extrapolation into the future/past" TF errors, see the TF2 section below.

TF Issues​

See TF2 for the full explanation of frames and transforms. Quick diagnostic sequence:

ros2 run tf2_ros tf2_echo <source_frame> <target_frame>
ros2 run tf2_tools view_frames
  • "Frame does not exist" — nothing has published a transform for that frame ID yet; check spelling and confirm the publishing node is running.
  • "Lookup would require extrapolation" — the requested timestamp is outside TF2's retained buffer; request the latest available transform instead of an explicit historical stamp unless that history is actually required.
  • RobotModel is frozen, broken, or jittering in RViz — check for missing or conflicting TF, timestamp or simulated-time problems, and missing or inconsistent /joint_states. During bag playback, also check whether recorded TF overlaps with transforms generated by live nodes such as robot_state_publisher.

Permissions​

Commands fail with permission-denied errors rather than ROS 2-specific errors.

  • Executable bit missing on a script-based node: chmod +x the file (Python entry points installed via setup.py/colcon do not usually need this, but manually invoked scripts sometimes do).
  • Device access (serial ports, USB cameras, CAN interfaces) commonly requires the user to be in a specific group (e.g., dialout) or requires udev rules — check the specific hardware driver's documentation for the exact group or rule required.
  • Container volume/user mismatches: files created inside a container may be owned by a different UID than your host user, which can block editing or deleting them from the host afterward.
  • rosdep permission errors — rosdep init typically requires elevated privileges because it creates system-level configuration:
    sudo rosdep init
    Run rosdep update as the normal user:
    rosdep update

Useful Commands​

# Environment
printenv ROS_DISTRO
printenv ROS_DOMAIN_ID
printenv RMW_IMPLEMENTATION
ros2 doctor --report

# Graph
ros2 node list
ros2 topic list -t
ros2 topic info <topic> -v
ros2 service list -t
ros2 action list -t

# TF
ros2 run tf2_ros tf2_echo <source_frame> <target_frame>
ros2 run tf2_tools view_frames

Key Takeaways​

  • Work through symptoms as categories (missing topics, type mismatch, QoS, Domain ID, DDS discovery, containers, timestamps, TF, permissions), not as one-off guesses.
  • ros2 topic info -v and ros2 doctor --report resolve a large fraction of "why isn't this working" questions on their own.
  • Nodes that should discover each other must normally use the same ROS_DOMAIN_ID. Their RMW implementations and discovery/transport settings must also be compatible; using the same RMW implementation can simplify troubleshooting, but it is not an absolute requirement.
  • TF and playback problems can result from missing transforms, timing issues, or conflicting TF authorities. During bag playback, ensure that overlapping transforms are not produced by multiple sources.

Next​

Return to the ROS 2 learning map if you have resolved your issue, or revisit ROS 2 Domain ID, TF2, or Rosbag for deeper detail on those specific topics.