CUDA-Q's errors have a different shape than the other SDKs on this list, because CUDA-Q kernels compile to run on GPU hardware rather than executing as plain Python. Most of what trips people up comes from treating a @cudaq.kernel function like ordinary Python, or from a CUDA toolkit mismatch underneath the SDK entirely.
CUDA toolkit and driver version mismatches
CUDA-Q is built against a specific CUDA toolkit major version, and installing it without a matching NVIDIA driver and toolkit on the machine produces install-time or import-time failures that point at CUDA, not at CUDA-Q's own code. Before installing, check nvidia-smi for your driver's supported CUDA version, and install the CUDA-Q build that matches it rather than assuming the latest CUDA-Q release supports whatever CUDA version happens to be on the machine. If GPU execution silently falls back to CPU with no error at all, this mismatch is the first thing worth checking, since CUDA-Q degrades gracefully to CPU simulation rather than failing loudly when it can't find a usable GPU target.
Code that isn't allowed inside @cudaq.kernel
@cudaq.kernel
def my_kernel():
qubits = cudaq.qvector(2)
data = [1, 2, 3] # plain Python list comprehension, unsupported
h(qubits[0])
Functions decorated with @cudaq.kernel get compiled to run on quantum (or simulated quantum) hardware, not interpreted as ordinary Python. That means only a restricted subset of the language is valid inside one: no arbitrary classes, no calls into NumPy or other Python libraries, and limited control-flow patterns compared to a normal function. Code that works fine outside a kernel raises a compile-time error the moment it's moved inside one. Keep classical data preparation (list building, NumPy work, file I/O) outside the kernel function, and pass only the values the kernel needs as arguments.
Forgetting to set the target before running
import cudaq
# no cudaq.set_target(...) call
result = cudaq.sample(my_kernel) # runs on the default target, not necessarily GPU
cudaq.sample() and cudaq.observe() run against whatever target is currently set, and the default isn't guaranteed to be the GPU-accelerated backend you might be assuming. If code runs correctly but slower than expected, or a colleague's identical code runs meaningfully faster, check whether cudaq.set_target("nvidia") (or whichever GPU target applies to the install) was called before execution:
cudaq.set_target("nvidia")
result = cudaq.sample(my_kernel, shots_count=1000)
Calling a kernel like a normal function
@cudaq.kernel
def bell():
q = cudaq.qvector(2)
h(q[0])
x.ctrl(q[0], q[1])
counts = bell() # doesn't do what it looks like it does
A @cudaq.kernel-decorated function isn't meant to be called directly the way a normal Python function is. It's meant to be passed to an execution entry point, cudaq.sample(), cudaq.observe(), cudaq.run(), which handles compiling and running it against the current target:
counts = cudaq.sample(bell, shots_count=1000)
Calling the kernel directly either raises an error or, depending on the CUDA-Q version, returns something that isn't the measurement result you're expecting. If output looks wrong in a way that doesn't match the circuit logic at all, check whether the kernel is being invoked directly instead of through cudaq.sample() or cudaq.observe().
The pattern behind most of these
CUDA-Q's errors mostly come from the gap between "looks like Python" and "compiles to run on GPU hardware." The kernel decorator boundary is where almost everything on this list breaks: what's valid inside it, what target it runs against, and how it gets invoked are all stricter than ordinary Python, because unlike a pure simulator SDK, CUDA-Q is compiling toward real accelerated execution underneath.