C.W.K.
Stream
Lesson 04 of 05 · published

Common jit Errors and Fixes

~8 min · jit, jax, tutorial

Level 0Curious
0 XP0/73 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

Let's walk through the most common errors you'll encounter with JIT and how to fix each one.

Error 1: ConcretizationTypeError

import jax
import jax.numpy as jnp

# Problem: Python if with traced value
@jax.jit
def categorize(x):
    if x > 0:       # ERROR!
        return 1
    elif x < 0:
        return -1
    else:
        return 0

# Fix: use jnp.sign (or jnp.where for custom logic)
@jax.jit
def categorize_fixed(x):
    return jnp.sign(x).astype(jnp.int32)

Error 2: Shapes Must Be Static

import jax
import jax.numpy as jnp

# Problem: dynamic output shape
@jax.jit
def filter_positive(x):
    return x[x > 0]  # Output size depends on values — not allowed!

# Fix 1: Use a fixed-size output with padding
@jax.jit
def filter_positive_fixed(x, max_size):
    mask = x > 0
    indices = jnp.where(mask, size=max_size, fill_value=0)
    return x[indices[0]]

# Fix 2: Don't JIT this particular function
# (sometimes the simplest answer)
def filter_positive_eager(x):
    return x[x > 0]  # Works fine without jit

Error 3: Python for-Loop Over Traced Values

import jax
import jax.numpy as jnp

# Problem: Python range with traced value
@jax.jit
def repeat_add(x, n):
    result = x
    for i in range(n):  # ERROR if n is traced
        result = result + x
    return result

# Fix 1: make n static
from functools import partial

@partial(jax.jit, static_argnums=(1,))
def repeat_add_static(x, n):
    result = x
    for i in range(n):  # n is concrete now — loop is unrolled
        result = result + x
    return result

# Fix 2: use jax.lax.fori_loop
@jax.jit
def repeat_add_functional(x, n):
    return jax.lax.fori_loop(0, n, lambda i, r: r + x, x)

When NOT to JIT

  • Debugging: Run without JIT first to get normal Python errors and print output.
  • One-off computations: If you call a function once, the compilation cost outweighs the benefit.
  • Highly dynamic shapes: If input shapes change every call, JIT will recompile every time, making it slower than eager mode.
  • Very small computations: The overhead of dispatching to XLA can exceed the computation time for tiny arrays.

💡 Why This Matters

JIT isn't always the right choice. The key heuristic is: JIT functions that get called repeatedly with the same shapes. Training step functions are ideal JIT candidates (called thousands of times with identical shapes). Data preprocessing with variable-length inputs is a poor candidate. When in doubt, benchmark both ways with jax.block_until_ready().

Code

import jax
import jax.numpy as jnp

# Problem: Python if with traced value
@jax.jit
def categorize(x):
    if x > 0:       # ERROR!
        return 1
    elif x < 0:
        return -1
    else:
        return 0

# Fix: use jnp.sign (or jnp.where for custom logic)
@jax.jit
def categorize_fixed(x):
    return jnp.sign(x).astype(jnp.int32)
import jax
import jax.numpy as jnp

# Problem: dynamic output shape
@jax.jit
def filter_positive(x):
    return x[x > 0]  # Output size depends on values — not allowed!

# Fix 1: Use a fixed-size output with padding
@jax.jit
def filter_positive_fixed(x, max_size):
    mask = x > 0
    indices = jnp.where(mask, size=max_size, fill_value=0)
    return x[indices[0]]

# Fix 2: Don't JIT this particular function
# (sometimes the simplest answer)
def filter_positive_eager(x):
    return x[x > 0]  # Works fine without jit
import jax
import jax.numpy as jnp

# Problem: Python range with traced value
@jax.jit
def repeat_add(x, n):
    result = x
    for i in range(n):  # ERROR if n is traced
        result = result + x
    return result

# Fix 1: make n static
from functools import partial

@partial(jax.jit, static_argnums=(1,))
def repeat_add_static(x, n):
    result = x
    for i in range(n):  # n is concrete now — loop is unrolled
        result = result + x
    return result

# Fix 2: use jax.lax.fori_loop
@jax.jit
def repeat_add_functional(x, n):
    return jax.lax.fori_loop(0, n, lambda i, r: r + x, x)

External links

Exercise

Hand-craft three minimal repros: (1) shape leak (calling shape on a tracer), (2) Python control flow on tracer (if x > 0:), (3) calling .item() on a traced value. For each, fix it. Save these as your personal jit-debug cheatsheet.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.