jax-ml/jax · error · ConcretizationTypeError

The delete() method was called on {self._error_repr()}.{self

Error message

The delete() method was called on {self._error_repr()}.{self._origin_msg()}

What it means

ConcretizationTypeError raised when Tracer.delete() is called. delete() explicitly frees a materialized jax.Array's device buffers; a tracer is an abstract placeholder produced during tracing and owns no memory, so the base-class stub raises instead of silently no-op'ing.

Source

Thrown at jax/_src/core.py:1239

    return self._pretty_print(verbose=False).format()

  def _contents(self):
    try:
      return [(name, getattr(self, name)) for name in self.__slots__]
    except AttributeError:
      return ()

  def _origin_msg(self) -> str:
    return ""

  # Methods that are only valid for materialized arrays
  def addressable_data(self, index):
    raise ConcretizationTypeError(self,
      f"The addressable_data() method was called on {self._error_repr()}."
      f"{self._origin_msg()}")

  def delete(self):
    raise ConcretizationTypeError(self,
      f"The delete() method was called on {self._error_repr()}."
      f"{self._origin_msg()}")

  def devices(self):
    raise ConcretizationTypeError(self,
      f"The devices() method was called on {self._error_repr()}."
      f"{self._origin_msg()}")

  @property
  def global_shards(self):
    raise ConcretizationTypeError(self,
      f"The global_shards property was called on {self._error_repr()}."
      f"{self._origin_msg()}")

  def is_deleted(self):
    raise ConcretizationTypeError(self,
      f"The is_deleted() method was called on {self._error_repr()}."
      f"{self._origin_msg()}")

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Move delete() calls to after the jitted/transformed function returns, operating on the concrete result array.
  2. Drop the delete() call inside the trace entirely; JAX's compiler already manages buffer lifetimes of traced intermediates.
  3. If freeing intermediates is the goal, rely on delete semantics on the output arrays or use jax.lax.scan/donate_argnums to control memory reuse.
  4. Guard with isinstance(x, jax.Array) before calling delete.

Example fix

// before
@jax.jit
def step(x):
    y = heavy(x)
    x.delete()  # ConcretizationTypeError
    return y

// after
@jax.jit
def step(x):
    return heavy(x)
# caller: buf.delete() on the concrete array if needed
Defensive patterns

Strategy: type-guard

Validate before calling

import jax

def safe_delete(x):
    if isinstance(x, jax.Array) and not isinstance(x, jax.core.Tracer):
        x.delete()
    # tracers: nothing to free

Type guard

import jax
from jax.core import Tracer

def can_delete(x) -> bool:
    return isinstance(x, jax.Array) and not isinstance(x, Tracer)

Try / catch

from jax.errors import ConcretizationTypeError
try:
    x.delete()
except ConcretizationTypeError:
    pass  # traced intermediates are compiler-managed

Prevention

When it happens

Trigger: Calling `x.delete()` on a traced value inside jit/grad/vmap/pmap/scan/remat or inside a custom JVP/VJP rule.

Common situations: Memory-management cleanup code (delete() to release large intermediates) reused inside a jitted function; trying to free buffers inside a training step that grad() traces through; batch-processing loop where del/delete calls ended up in the traced region.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/fe229ed83732e9e8. Report an issue: GitHub.