Repository: zarr-developers/zarr-python

Issue:
Unexpected Vectorized Indexing Setting Behavior
### Zarr version

v3.0.0-beta.1 (main)

### Numcodecs version

0.13.0

### Python Version

3.12

### Operating System

Mac

### Installation

`uv` from repo

### Description

I think this is vectorized indexing...in any case I think that the following example should error since `arr[:][[np.array([1, 2]), np.array([1, 2])]]` is 1d but it allows storing a 2d

### Steps to reproduce

```python
import tempfile
import numpy as np
import zarr
from zarr.storage import LocalStore

shape = (4, 4)
chunks = (2, 2)
fill_value = 32767

tmp = tempfile.TemporaryDirectory()
arr = zarr.create(
    shape,
    store=LocalStore(root=tmp.name, mode="w"),
    chunks=chunks,
    dtype=np.int16,
    fill_value=fill_value,
    codecs=[zarr.codecs.BytesCodec(), zarr.codecs.BloscCodec()],
)

arr[np.array([1, 2]), np.array([1, 2])] = np.array([[-1, -2], [-3, -4]])
print(arr[:])
```
gives
```
[[32767 32767 32767 32767]
 [32767    -1 32767 32767]
 [32767 32767    -2 32767]
 [32767 32767 32767 32767]]
```
which I would not expect - I would probably expect this to error.

### Additional output

_No response_

Discussion:

Patch:
diff --git a/src/zarr/core/array.py b/src/zarr/core/array.py
index 71a6f9d3..a6317e7a 100644
--- a/src/zarr/core/array.py
+++ b/src/zarr/core/array.py
@@ -2881,6 +2881,14 @@ class Array:
         if hasattr(value, "shape") and len(value.shape) > 1:
             value = np.array(value).reshape(-1)
 
+        if not is_scalar(value, self.dtype) and (
+            isinstance(value, NDArrayLike) and indexer.shape != value.shape
+        ):
+            raise ValueError(
+                f"Attempting to set a selection of {indexer.sel_shape[0]} "
+                f"elements with an array of {value.shape[0]} elements."
+            )
+
         sync(self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype))
 
     @_deprecate_positional_args


Test patch:
diff --git a/tests/test_indexing.py b/tests/test_indexing.py
index 3dc93ba4..04eb53e3 100644
--- a/tests/test_indexing.py
+++ b/tests/test_indexing.py
@@ -1936,3 +1936,21 @@ def test_zero_sized_chunks(store: StorePath, shape: list[int]) -> None:
     z = Array.create(store=store, shape=shape, chunk_shape=shape, zarr_format=3, dtype="f8")
     z[...] = 42
     assert_array_equal(z[...], np.zeros(shape, dtype="f8"))
+
+
+@pytest.mark.parametrize("store", ["memory"], indirect=["store"])
+def test_vectorized_indexing_incompatible_shape(store) -> None:
+    # GH2469
+    shape = (4, 4)
+    chunks = (2, 2)
+    fill_value = 32767
+    arr = zarr.create(
+        shape,
+        store=store,
+        chunks=chunks,
+        dtype=np.int16,
+        fill_value=fill_value,
+        codecs=[zarr.codecs.BytesCodec(), zarr.codecs.BloscCodec()],
+    )
+    with pytest.raises(ValueError, match="Attempting to set"):
+        arr[np.array([1, 2]), np.array([1, 2])] = np.array([[-1, -2], [-3, -4]])