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
- Move delete() calls to after the jitted/transformed function returns, operating on the concrete result array.
- Drop the delete() call inside the trace entirely; JAX's compiler already manages buffer lifetimes of traced intermediates.
- 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.
- 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
- Put memory-freeing logic in the outer driver, never inside jit/grad bodies.
- Use donate_argnums for buffer donation instead of manual delete.
- Guard shared cleanup helpers with isinstance(x, jax.Array).
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
- The is_deleted() method was called on {self._error_repr()}.{
- The addressable_data() method was called on {self._error_rep
- The devices() method was called on {self._error_repr()}.{sel
- The global_shards property was called on {self._error_repr()
- The is_fully_addressable property was called on {self._error
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/fe229ed83732e9e8.
Report an issue: GitHub.