teenygrad kernels / Reference

Common Compile Errors

Errors you will actually hit, with the real text and the fix. Grouped by which compiler produced them, because that tells you where to look.

From the #[kernel] macro

These come from the proc macro, at ordinary cargo build time.


#[kernel] requires a type parameter with a `Triton` bound

Cause. The macro finds the GPU by looking for the type parameter bounded by Triton. Yours has none.

Fix. Add it. Every kernel starts:

pub fn my_kernel<T: Triton, D: Num, const BLOCK_SIZE: i32>(...)

This is also what you get if you wrote Triton but did not import it.


`dtypes` must be a list, e.g. `dtypes = [f32, f64]`

Cause. #[kernel(dtypes = f32)] — a bare name where a list belongs.

Fix. Brackets: #[kernel(dtypes = [f32])].


`f16` is not a known scalar dtype

Or any other name. Cause. The dtype list only accepts scalar dtype identifiers: bool, i8i64, u8u64, f16, bf16, f32, f64.

Fix. Use one of those. Note that f16 and bf16 parse but cannot be monomorphized — see Chapter 15 and KNOWN-GAPS.md item 4.


duplicate dtype `f32` in `dtypes`

Fix. Remove the repeat.


unknown `#[kernel]` argument `dtype` (expected `dtypes` or `backward`)

Cause. A typo. There are exactly two arguments.


cannot infer supported dtypes: a `#[kernel]` that opts into dispatch without an
explicit `dtypes = [..]` must have a dtype type parameter bound by one of
Dtype/Num/Int/Float/Bool

Cause. You used #[kernel(backward = ...)], which opts into dispatch, but your dtype parameter is bounded by something the macro cannot expand into a dtype set.

Fix. Either bound it by one of the five, or list the dtypes explicitly. Chapter 15 has the table.

From rustc, about kernel bodies


the trait bound `<T as Triton>::Pointer<D>: AddOffsets<...>` is not satisfied

Cause. A missing where clause. This is the most common error in a first kernel, and it means you called add_offsets without declaring that you would.

Fix. The three clauses every kernel carries:

where
    T::I32Tensor: types::Tensor<i32, 1>,
    T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
    T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,

Copy them verbatim. They are identical in every kernel in this tree, which is the first item in API-FRICTION.md.


expected fn pointer `fn(...) -> ...`
   found closure `[closure@src/kernels/mine.rs:42:30]`

Cause. A closure passed to T::reduce or T::associative_scan.

Fix. Make it a named function. The combine function is compiled from captured source text, so it must be statically known — Chapter 13. The error does not mention kernels at all, which is why it belongs on this list.


no method named `lt` found for associated type `<T as Triton>::I32Tensor`

Cause. The Comparison trait is not in scope, or its where clause is missing.

Fix. use teeny_triton::triton::types::Comparison; — usually already covered by the glob import every kernel starts with.


mismatched types
   expected `Option<<T as Triton>::BoolTensor>`
      found `Option<<T as Triton>::I32Tensor>`

Cause. An integer tensor used as a mask. A mask must come from a comparison.

Fix. Some(offsets.lt(n)), not Some(offsets).

From teenyc

These appear when compile_kernel runs, which is at run time — Chapter 3.


no teenyc rustup toolchain found; set TEENYC_PATH to the teenyc binary, or
install one with `cargo teeny install-toolchain` (see cargo-teeny)

Fix. Either install it, or set TEENYC_PATH. Chapter 4. There is deliberately no fallback to a bare teenyc on $PATH.


multiple teenyc rustup toolchains found (a, b); set TEENYC_PATH to disambiguate

Fix. Set TEENYC_PATH to the one you want.


A teenyc failure mentioning names you did not use. The kernel body is compiled against a small generated environment, not your crate. println!, your own helper functions, and most of std are not there.

Fix. Use only the Triton trait and plain arithmetic in a kernel body. For printing, T::device_print.

From the CUDA driver

At load time, when the PTX becomes machine code.


PTX .version 8.6 does not support .target sm_120a

Cause. teenyc’s default PTX version is newer than your driver accepts. Seen on Blackwell.

Fix. TEENYC_PTX_VERSION=87. A teenyc-side default; the SDK cannot work around it.


wrapper.h:17:10: fatal error: 'cuda.h' file not found

Cause. Not a kernel error at all — teeny-cuda’s build.rs generating bindings, with no CUDA toolkit installed. A driver alone is not enough.

Fix. Install the toolkit, or build without the cuda feature. Chapter 4.


custom op 'my.op' is not handled — implement CustomOp::lower()

Cause. A CustomOp whose lower still returns the default None.

Fix. Implement it. Chapter 20.

Things that do not error

The worst list, because there is nothing to search for.

Symptom Likely cause
Wrong numbers, no crash Argument order in pack_args or the launch tuple. Nothing checks it
Wrong numbers only at the end of a buffer Missing mask. Chapter 7
Wrong reduction results Masked lanes not filled with the identity. Chapter 10
Gradients all zero has_backward not overridden, or backward_grid left at its [0,0,0] default. Chapter 22
Results differ run to run Atomics. Expected; compare with a tolerance. Chapter 14
Correct but slow after a port Block size tuned for a different card. Chapter 24
Kernel silently does nothing Calling the #[kernel] function directly. It is not the kernel; the struct is

For any of these, the first move is Chapter 9: read the MLIR. Count the loads and stores, check the constants, and look for the mask operand.