Why AI Coding Assistants Don't Work for ROS2 (And It's Not the Syntax)
The code compiled. The node launched. The robot didn't move. I stared at the executor pattern Cursor had generated for ten minutes before realizing it was wrong in a way that no error message was ever

David Díaz
Co-Founder
The code compiled. The node launched. The robot didn't move. I stared at the executor pattern Cursor had generated for ten minutes before realizing it was wrong in a way that no error message was ever going to surface. That's the real failure mode of general-purpose AI coding assistants on ROS2 — not syntax errors you can catch, but plausible-looking code that silently misbehaves.
The Problem Is Not That LLMs Are Bad
Let me be direct about something: Copilot, Cursor, and Claude Code are genuinely good tools. I use them every day building Nodeably. For Python scripts, API clients, TypeScript interfaces, database queries — they're fast and they're mostly right.
The failure on ROS2 is not a quality problem. It's a mismatch problem. ROS2 is not a standard programming environment. It's a distributed middleware framework with version-locked release trains, a DDS communication layer with configuration options that affect runtime behavior without affecting compilation, and a node/executor model where the wrong pattern produces deadlocks or dropped messages that look like intermittent bugs. The surface area of "things that can go wrong silently" is unusually large.
When you ask a general-purpose assistant to write a lifecycle node with composable component loading, you get something that reflects the training distribution — which is broad documentation and example code, not production-grade ROS2 running on real hardware. The result compiles. It might even work in basic tests. Then it breaks in ways that take hours to trace.
Three Specific Ways This Breaks
Executor and callback group patterns. ROS2's executor model is genuinely poorly documented, particularly around nested callbacks. If you have a timer calling a service from within a callback, you need a multi-threaded executor with explicitly separate callback groups. Ask Cursor or Claude Code to write this and you'll likely get a single-threaded executor with no callback group configuration — code that compiles, runs, and deadlocks when the service call tries to reenter the executor. No error. Just silence.
DDS configuration. The choice of DDS middleware and its configuration — QoS profiles, transport settings, domain IDs — is invisible to a general coding assistant because it lives outside the code files themselves. An assistant generating a subscriber node has no way of knowing you're running on a network with unreliable multicast, or that your publisher is using BEST_EFFORT reliability. The generated code is valid. The data never arrives. This is the class of problem the ROS Discourse community describes as composable nodes used as an undocumented workaround rather than a configuration the tooling surfaced.
Hallucinated packages. Research from 2025 puts the rate of hallucinated package names in LLM-generated code at roughly 20% across general codebases. ROS2 makes this worse. The package ecosystem is version-locked to ROS2 distributions — a package that exists in Humble may not exist in Iron, and the naming conventions aren't always consistent. An assistant generating a CMakeLists.txt or package.xml with incorrect dependency names will produce something that fails at build time if you're lucky, or silently mislinks at runtime if you're not. There's now an active security concern here too: researchers have named "slopsquatting" as an attack vector that exploits AI-hallucinated package names. For robotics teams deploying on physical systems, that's not a theoretical risk.
What Engineers Are Doing Right Now
The community has noticed. There's a GitHub repository — robotics-agent-skills — that exists specifically to make Claude Code and Cursor write production-grade ROS2 code. It provides SKILL.md files you manually inject into your prompts to give the model the domain context it's missing natively. That's the state of the art right now: engineers hand-crafting scaffolding files to patch the context gap in tools that weren't built for this problem.
AgenticROS takes a different approach and connects ROS2 directly to Claude Code and Gemini at the DDS layer, running the AI on the robot's computer. It works, but it's tightly coupled, requires the model to be colocated with the DDS network, and still doesn't solve the problem of the model lacking awareness of your specific workspace, your specific package versions, or the accumulated decisions in your codebase.
These projects exist because the gap is real and the available tools don't close it. People are solving it by hand because there's nothing else.
What Would Actually Make It Work
The category of problems above share a root cause: general-purpose assistants operate without project context. They don't know your ROS2 distribution, your workspace structure, your existing nodes and their interfaces, or your DDS configuration. They generate code as if every project is a blank slate.
A tool that actually works for ROS2 needs four things that general assistants don't have:
First, persistent workspace context — awareness of the packages in your workspace, their dependencies, their interfaces, and how they relate to each other. Not just the file you have open right now.
Second, distribution-specific package knowledge — the ability to resolve package names and APIs against a specific ROS2 release, not against a mixed training distribution from multiple versions.
Third, executor and DDS pattern awareness — the common architectural patterns in ROS2 that are either undocumented or documented poorly enough that LLMs consistently get them wrong.
Fourth, some form of validation that isn't "does it compile" — because the failure mode we're discussing is precisely the code that passes compilation and fails at runtime. You need awareness of the behavioral invariants that matter.
I want to be honest about what's hard here: persistent workspace context is an unsolved problem even in general-purpose coding assistants. It's the thing that makes ROS2 harder than most domains, not easier. The workspace in ROS2 is a dependency graph, not just a set of files. Building a tool that understands it deeply enough to be useful — not just helpful-looking — is the actual engineering challenge.
That's what we're working on at Nodeably. Not another wrapper around an LLM with a ROS2 prompt. Something that actually understands the workspace.
Continue reading
Related Posts
Python ROS2 Nodes Start Fine. Then the Callbacks Start Drifting.
Most ROS2 teams start in Python. The API is cleaner. Iteration is faster. rclpy handles the majority of nodes without issue. Then at some point a timer fires late, a high-frequency publisher drops mes
May 26, 2026
ROS2 on Mac or Windows Means Docker. That Sentence Costs More Than Most Teams Realize.
ROS2 is Linux-native. That is not a complaint about the design choice — Linux is the right foundation for production robotics. The complaint is about what the development toolchain assumes: that every
May 26, 2026
Your ROS2 Subscriber Is Not Receiving Messages. No Error. No Warning. Nothing.
Your publisher is running. `ros2 topic echo` shows data flowing out. Your subscriber node is alive. The callback never fires. No error in the log. No warning on the console. Nothing. This is a QoS mis
May 26, 2026