{"record":{"id":"aac854e021ea0221","repo":"jax-ml/jax","slug":"value-of-type-type-self-is-not-indexable","errorCode":null,"errorMessage":"Value of type {type(self)} is not indexable.","messagePattern":"Value of type (.+?) is not indexable\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"jax/_src/core.py","lineNumber":1162,"sourceCode":"    return self.aval._oct(self)\n\n  def __index__(self):\n    if is_concrete(self): return operator.index(self.to_concrete_value())\n    check_integer_conversion(self)\n    if not hasattr(self.aval, \"_index\"):\n      raise TypeError(f\"Value of type {type(self)} is not convertible to integer index.\")\n    return self.aval._index(self)\n\n  # raises a useful error on attempts to pickle a Tracer.\n  def __reduce__(self):\n    raise ConcretizationTypeError(\n      self, (\"The error occurred in the __reduce__ method, which may \"\n             \"indicate an attempt to serialize/pickle a traced value.\"))\n\n  # raises the better error message from ShapedArray\n  def __setitem__(self, key, value):\n    if not hasattr(self.aval, \"_setitem\"):\n      raise TypeError(f\"Value of type {type(self)} is not indexable.\")\n    return self.aval._setitem(self, key, value)\n\n  # NumPy also only looks up special methods on classes.\n  def __array_module__(self, types):\n    if not hasattr(self.aval, \"_array_module\"):\n      raise TypeError(f\"Value of type {type(self)} is not compatible with the Array API.\")\n    return self.aval._array_module(self, types)\n\n  def __getattr__(self, name):\n    # if the aval property raises an AttributeError, gets caught here\n    assert not config.enable_checks.value or name != \"aval\"\n\n    # These must raise AttributeError in the base class for backward compatibility.\n    # TODO(jakevdp): can we change this and make them raise NotImplementedError instead?\n    if name in [\"block_until_ready\", \"copy_to_host_async\"]:\n      raise AttributeError(\n        f\"The '{name}' method is not available on {self._error_repr()}.\"\n        f\"{self._origin_msg()}\")","sourceCodeStart":1144,"sourceCodeEnd":1180,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/core.py#L1144-L1180","documentation":"Raised by JAXTracer.__setitem__ when item assignment (x[idx] = value) is attempted on a Tracer whose aval does not support mutation (arrays in JAX are immutable). JAX arrays and tracers cannot be modified in place, so __setitem__ is blocked with a TypeError; the comment notes ShapedArray provides a more detailed message for the common array case.","triggerScenarios":"In-place updates like x[0] = 1.0 or x[i, j] += 1 on a traced array inside jit/grad/vmap; initializing an output buffer with loop writes inside a jitted function; adapting NumPy mutation-style code without rewrite.","commonSituations":"Porting NumPy algorithms (Gauss-Seidel sweeps, buffer accumulation, mask assignment) directly into @jax.jit; trying to fill a preallocated array inside lax.scan bodies or vmap-mutated state; accumulation patterns like grads[mask] = 0.","solutions":["Use jax.numpy .at: x = x.at[i].set(v), x = x.at[i].add(v), x = x.at[mask].set(v) — functional updates that work under tracing.","Restructure accumulation into carried state in jax.lax.scan/fori_loop (return new arrays each iteration).","Use jnp.where for mask-based assignment instead of boolean-mask setitem.","Allocate and fully construct new arrays (jnp.zeros(...).at[...].set(...)) rather than mutating inputs."],"exampleFix":"# before\n@jax.jit\ndef f(x):\n    x[0] = 1.0        # TypeError: not indexable / arrays are immutable\n    return x\n\n# after\n@jax.jit\ndef f(x):\n    return x.at[0].set(1.0)","handlingStrategy":"validation","validationCode":"import jax.numpy as jnp\ndef safe_set(x, idx, v):\n    return x.at[idx].set(v)   # works for both concrete arrays and tracers","typeGuard":"def is_mutable_host_array(x) -> bool:\n    import numpy as np\n    return isinstance(x, np.ndarray)","tryCatchPattern":null,"preventionTips":["Use the functional .at[].set()/.add() API everywhere in JAX code; it works under all transforms.","Carry updated buffers as scan/fori_loop state instead of mutating in place.","Replace boolean mask assignment with jnp.where.","Static-check traced functions for `] =` / `] +=` patterns during code review."],"tags":["jax","tracer","immutable-arrays","setitem","functional-updates"],"backgroundTag":"immutable-array-assignment","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}