jax-ml/jax · error · ValueError

fill_value argument to indexed get() must be a scalar

Error message

fill_value argument to indexed get() must be a scalar

What it means

For indexed get() with a fill_value (drop/fill out-of-bounds mode), the fill value must be a 0-dimensional scalar so a single fill element can be scattered for all OOB positions.

Source

Thrown at jax/_src/numpy/indexing.py:1217

  return result


# TODO(phawkins): re-enable jit after fixing excessive recompilation for
# slice indexes (e.g., slice(0, 5, None), slice(10, 15, None), etc.).
# @api.jit(static_argnums=(1, 2))
def _gather(arr, dynamic_idx, *, treedef, indices_are_sorted,
            unique_indices, mode, fill_value, normalize_indices):
  parsed_idx = tree_unflatten(treedef, dynamic_idx)
  indexer = parsed_idx.to_gather(core.typeof(arr).sharding,
                                 normalize_indices=normalize_indices)
  jnp_error._check_precondition_oob_gather(arr.shape, indexer.gather_indices)
  y = arr

  if fill_value is not None:
    core.concrete_or_error(None, fill_value,
                           "fill_value argument to indexed get()")
    if np.ndim(fill_value) != 0:
      raise ValueError("fill_value argument to indexed get() must be a scalar")
    if isinstance(fill_value, np.ndarray):
      fill_value = fill_value.item()

  if indexer.scalar_bool_dims:
    y = lax.expand_dims(y, indexer.scalar_bool_dims)

  # Avoid calling gather if the slice shape is empty, both as a fast path and to
  # handle cases like zeros(0)[array([], int32)].
  if core.is_empty_shape(indexer.slice_shape):
    return lax.full_like(y, 0, shape=indexer.slice_shape,
                         sharding=indexer.slice_sharding)

  # We avoid generating a gather when indexer.gather_indices.size is empty.
  if not core.is_empty_shape(indexer.gather_indices.shape):
    y = slicing.gather(
        y, indexer.gather_indices, indexer.dnums, indexer.gather_slice_shape,
        unique_indices=unique_indices or indexer.unique_indices,
        indices_are_sorted=indices_are_sorted or indexer.indices_are_sorted,

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Pass a scalar: fill_value=0 or fill_value=jnp.asarray(0.0, dtype=arr.dtype)
  2. Squeeze/convert arrays: fill_value=jnp.asarray(fv).reshape(()) or use .item()

Example fix

// before
y = x.at[idx].get(mode='fill', fill_value=[0])
// after
y = x.at[idx].get(mode='fill', fill_value=0)
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np
assert np.ndim(fill_value) == 0, 'fill_value must be scalar'

Type guard

def is_scalar_fill(f) -> bool:
    import numpy as np
    return np.ndim(f) == 0

Prevention

When it happens

Trigger: Calling arr.at[idx].get(mode='fill', fill_value=jnp.array([0, 0])) or passing a shape-(1,) array/list as fill_value instead of a scalar.

Common situations: Passing a list like [0] or a 1-element array instead of 0; constructing fill values dynamically with an unexpected leading dimension.

Related errors


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