jax-ml/jax · error · ValueError

other cannot be a block if pointer is not a block

Error message

other cannot be a block if pointer is not a block

What it means

When the loaded pointer is NOT a block (not a RankedTensorType), the load is a scalar load; supplying an `other` value that IS a block (tensor) is then shape-inconsistent and rejected before emitting tt.load.

Source

Thrown at jax/_src/pallas/triton/lowering.py:2048

    except KeyError:
      raise ValueError(
          f"unsupported eviction policy: {eviction_policy}"
      ) from None

  if _is_triton_pointer_type(ptr.type):
    ptr_type = tt_dialect.PointerType(ptr.type)
    if isinstance(ptr_type.pointee_type, ir.RankedTensorType):
      raise NotImplementedError("loading from a block pointer is not supported")

  ptr_type = _element_type(ptr.type)
  if not _is_triton_pointer_type(ptr_type):
    raise ValueError(f"unsupported pointer type: {ptr_type}")
  ptr_type = tt_dialect.PointerType(ptr_type)
  if other is not None and mask is None:
    raise ValueError("other requires mask to be provided")
  if not isinstance(ptr.type, ir.RankedTensorType):
    if other is not None and isinstance(other.type, ir.RankedTensorType):
      raise ValueError("other cannot be a block if pointer is not a block")
    if mask is not None and isinstance(mask.type, ir.RankedTensorType):
      raise ValueError("mask cannot be a block if pointer is not a block")

  pointee_type = ptr_type.pointee_type
  is_int1 = isinstance(pointee_type, ir.IntegerType) and pointee_type.width == 1
  if is_int1:
    pointee_type = ir.IntegerType.get_signless(8)
    ptr = _ir_cast(
        ptr,
        tt_dialect.PointerType.get(pointee_type, ptr_type.address_space),
        signed=False,
    )

  if other is not None:
    other = _ir_cast(other, pointee_type, signed=False)

  result = tt_dialect.load(
      ptr,

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Make other a scalar matching the pointee type when the pointer is scalar
  2. Or make the load a proper block load (mask + block-shaped pointer) if you want vector semantics
  3. Remove other for unmasked scalar loads

Example fix

// before
v = pl.load(scalar_ref, mask=m, other=jnp.zeros((B,)))

// after
v = pl.load(scalar_ref, mask=m, other=0.0)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def check_scalar_load(ptr_is_block, other):
    if not ptr_is_block and other is not None:
        assert not hasattr(other, 'shape') or np.ndim(other) == 0, 'other must be scalar for scalar loads'

Type guard

def other_matches_pointer(ptr_is_block: bool, other) -> bool:
    if other is None:
        return True
    other_is_block = getattr(other, 'shape', ()) != ()
    return ptr_is_block or not other_is_block

Try / catch

try:
    v = pl.load(ref, mask=m, other=fill)
except ValueError:
    v = pl.load(ref, mask=m, other=float(fill))  # scalarize

Prevention

When it happens

Trigger: Scalar pointer load combined with a tensor-typed other value, e.g. loading a single element with other=jnp.zeros(block_shape) inside a Triton Pallas kernel.

Common situations: Reusing a block-shaped default value from another load site in a scalar context; copy-paste of masked load scaffolding into scalar loads.

Related errors


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