numpy/numpy · error · TypeError

{_block_format_index(parent_index)} is a tuple. Only lists c

Error message

{_block_format_index(parent_index)} is a tuple. Only lists can be used to arrange blocks, and np.block does not allow implicit conversion from tuple to ndarray.

What it means

Raised by np.block's depth-checker when it encounters a tuple nested inside the block structure. np.block deliberately only accepts lists for arranging blocks and refuses to implicitly convert a tuple into an ndarray, because treating a tuple as data would be ambiguous.

Source

Thrown at numpy/_core/shape_base.py:592

    -------
    first_index : list of int
        The full index of an element from the bottom of the nesting in
        `arrays`. If any element at the bottom is an empty list, this will
        refer to it, and the last index along the empty axis will be None.
    max_arr_ndim : int
        The maximum of the ndims of the arrays nested in `arrays`.
    final_size: int
        The number of elements in the final array. This is used the motivate
        the choice of algorithm used using benchmarking wisdom.

    """
    if isinstance(arrays, tuple):
        # not strictly necessary, but saves us from:
        #  - more than one way to do things - no point treating tuples like
        #    lists
        #  - horribly confusing behaviour that results when tuples are
        #    treated like ndarray
        raise TypeError(
            f'{_block_format_index(parent_index)} is a tuple. '
            'Only lists can be used to arrange blocks, and np.block does '
            'not allow implicit conversion from tuple to ndarray.'
        )
    elif isinstance(arrays, list) and len(arrays) > 0:
        idxs_ndims = (_block_check_depths_match(arr, parent_index + [i])
                      for i, arr in enumerate(arrays))

        first_index, max_arr_ndim, final_size = next(idxs_ndims)
        for index, ndim, size in idxs_ndims:
            final_size += size
            if ndim > max_arr_ndim:
                max_arr_ndim = ndim
            if len(index) != len(first_index):
                raise ValueError(
                    "List depths are mismatched. First element was at "
                    f"depth {len(first_index)}, but there is an element at "
                    f"depth {len(index)} ({_block_format_index(index)})"

View on GitHub (pinned to e117b3ca4e)

Solutions

  1. Replace any tuple grouping with a list: use [...] not (...) for block rows.
  2. Convert tuple inputs to lists: [list(t) for t in rows].
  3. If a tuple is meant to be a single array operand, wrap it with np.array(t) first.

Example fix

// before
np.block([[a, b], (c, d)])
// after
np.block([[a, b], [c, d]])
Defensive patterns

Strategy: type-guard

Validate before calling

def no_tuples(node):
    if isinstance(node, tuple):
        raise TypeError('np.block expects lists, not tuples')
    if isinstance(node, list):
        for x in node: no_tuples(x)
no_tuples(arrays)

Type guard

def block_is_list_only(node):
    if isinstance(node, tuple): return False
    if isinstance(node, list):
        return all(block_is_list_only(x) for x in node)
    return True

Prevention

When it happens

Trigger: Calling np.block([...]) where one of the nested elements is a tuple instead of a list or array, e.g. np.block([[a, b], (c, d)]).

Common situations: Using parentheses out of habit for grouping instead of brackets; a function returning a tuple that is fed directly into block; converting a list literal to a tuple inadvertently.

Related errors


AI-assisted analysis of numpy/numpy@e117b3ca4e (2026-08-07). Data as JSON: /api/errors/d9d4a695ed0bbd8f. Report an issue: GitHub.