Describe the bug
zonal.apply() checks the shape of zones against values with zones.shape != values.shape[:2], then dispatches to a backend based on the type of values. It only calls validate_arrays(zones, values) for the 2D case. For 3D values, backend compatibility between zones and values is never checked.
Mixed dask/numpy inputs slip through:
zones is numpy and values is dask: the dask backend runs and tries zones_data.chunks, which raises AttributeError: 'numpy.ndarray' object has no attribute 'chunks'.
zones is dask and values is numpy: the numpy backend runs and silently returns eager numpy output, ignoring that zones was chunked.
Neither outcome is a clear, early error.
Expected behavior
Mixed-backend zones and values should fail early with a clear error, the same way validate_arrays reports a backend mismatch elsewhere in the module. The 2D path already does this; the 3D path should too.
Additional context
The 2D path calls validate_arrays(zones, values), which checks both shape and backend. The 3D path skips it because validate_arrays requires equal full shapes, and a 2D zones cannot equal a 3D values. The fix is to validate backend compatibility for the 3D case without requiring equal full shapes.
Describe the bug
zonal.apply()checks the shape ofzonesagainstvalueswithzones.shape != values.shape[:2], then dispatches to a backend based on the type ofvalues. It only callsvalidate_arrays(zones, values)for the 2D case. For 3Dvalues, backend compatibility betweenzonesandvaluesis never checked.Mixed dask/numpy inputs slip through:
zonesis numpy andvaluesis dask: the dask backend runs and trieszones_data.chunks, which raisesAttributeError: 'numpy.ndarray' object has no attribute 'chunks'.zonesis dask andvaluesis numpy: the numpy backend runs and silently returns eager numpy output, ignoring thatzoneswas chunked.Neither outcome is a clear, early error.
Expected behavior
Mixed-backend
zonesandvaluesshould fail early with a clear error, the same wayvalidate_arraysreports a backend mismatch elsewhere in the module. The 2D path already does this; the 3D path should too.Additional context
The 2D path calls
validate_arrays(zones, values), which checks both shape and backend. The 3D path skips it becausevalidate_arraysrequires equal full shapes, and a 2Dzonescannot equal a 3Dvalues. The fix is to validate backend compatibility for the 3D case without requiring equal full shapes.