jax-ml/jax · error · TypeError

dot_general requires rhs dimension numbers to be nonnegative

Error message

dot_general requires rhs dimension numbers to be nonnegative and less than the number of axes of the rhs value, got rhs_batch of {rhs_batch} and rhs_contracting of {rhs_contracting} for rhs of rank {rhs.ndim}

What it means

Same bounds check as 917 but for the rhs operand: every dimension index in rhs_contracting and rhs_batch must satisfy 0 <= d < rhs.ndim. Negative indices (not supported) or indices at/above the rank raise TypeError echoing the lists and rhs rank.

Source

Thrown at jax/_src/lax/lax.py:5702

                            preferred_element_type: DTypeLike | None,
                            out_sharding):
  if out_sharding is not None and not isinstance(out_sharding, NamedSharding):
    raise NotImplementedError
  (lhs_contracting, rhs_contracting), (lhs_batch, rhs_batch) = _from_maybe_ragged(dimension_numbers)
  if not all(np.all(np.greater_equal(d, 0)) and np.all(np.less(d, lhs.ndim))
             for d in (lhs_contracting, lhs_batch)):
    msg = ("dot_general requires lhs dimension numbers to be nonnegative and "
           "less than the number of axes of the lhs value, got "
           f"lhs_batch of {lhs_batch} and lhs_contracting of {lhs_contracting} "
           f"for lhs of rank {lhs.ndim}")
    raise TypeError(msg)
  if not all(np.all(np.greater_equal(d, 0)) and np.all(np.less(d, rhs.ndim))
             for d in (rhs_contracting, rhs_batch)):
    msg = ("dot_general requires rhs dimension numbers to be nonnegative and "
           "less than the number of axes of the rhs value, got "
           f"rhs_batch of {rhs_batch} and rhs_contracting of {rhs_contracting} "
           f"for rhs of rank {rhs.ndim}")
    raise TypeError(msg)
  if len(lhs_batch) != len(rhs_batch):
    msg = ("dot_general requires equal numbers of lhs_batch and rhs_batch "
           "dimensions, got lhs_batch {} and rhs_batch {}.")
    raise TypeError(msg.format(lhs_batch, rhs_batch))
  lhs_contracting_set, lhs_batch_set = set(lhs_contracting), set(lhs_batch)
  rhs_contracting_set, rhs_batch_set = set(rhs_contracting), set(rhs_batch)
  if len(lhs_batch_set) != len(lhs_batch):
    msg = ("dot_general requires lhs batch dimensions to be distinct, got "
           f"lhs_batch {lhs_batch}.")
    raise TypeError(msg)
  if len(rhs_batch_set) != len(rhs_batch):
    msg = ("dot_general requires rhs batch dimensions to be distinct, got "
           f"rhs_batch {rhs_batch}.")
    raise TypeError(msg)
  if len(lhs_contracting_set) != len(lhs_contracting):
    msg = ("dot_general requires lhs contracting dimensions to be distinct, "
           f"got lhs_contracting {lhs_contracting}.")
    raise TypeError(msg)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Clamp rhs indices to [0, rhs.ndim)
  2. Ensure the rhs lists are in the second position of each pair: ((lhs_c, rhs_c), (lhs_b, rhs_b))
  3. Use tensordot/einsum for readability when hand-building contractions
  4. Print rhs.ndim and the dimension_numbers to spot the offending index

Example fix

// before
out = lax.dot_general(a, b, ((1,), (2,)), ((), ()))  # b has rank 2

// after
out = lax.dot_general(a, b, ((1,), (1,)), ((), ()))
Defensive patterns

Strategy: validation

Validate before calling

assert all(0 <= d < rhs.ndim for d in (*rhs_contracting, *rhs_batch)), 'bad rhs dims'

Type guard

def valid_rhs_dims(dn, rhs) -> bool:
    (_, rc), (_, rb) = dn
    return all(0 <= d < rhs.ndim for d in (*rc, *rb))

Prevention

When it happens

Trigger: lax.dot_general with rhs contracting dim equal to rhs.ndim, or a negative rhs batch index; swapping lhs/rhs dimension lists so rhs gets lhs-range indices.

Common situations: Asymmetric tensor contractions where lhs and rhs have different ranks; copy-paste of dimension_numbers between calls with different operands; negative-axis habits from numpy.

Related errors


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