Summary
After rebuilding a fresh environment SpatialData.write() started failing.
The same code works in an older environment with the same spatialdata, dask, and zarr versions, but with ome-zarr==0.13.0 instead of 0.14.0.
This looks like a regression at the spatialdata / ome-zarr boundary when chunks are passed from xarray/dask to the writer.
Minimal reproducer
import os
import tempfile
from spatialdata.datasets import blobs
sdata = blobs()
out = os.path.join(tempfile.gettempdir(), "sd_blobs_write_issue.zarr")
sdata.write(out)
Observed behavior
The call to sdata.write(out) raises:
TypeError: Expected an iterable of integers. Got ((3,), (512,), (512,)) instead.
Full traceback
Traceback (most recent call last):
File "<stdin>", line 9, in <module>
File ".../site-packages/spatialdata/_utils.py", line 263, in wrapper
return f(*args, **kwargs)
File ".../site-packages/spatialdata/_core/spatialdata.py", line 1176, in write
self._write_element(
File ".../site-packages/spatialdata/_core/spatialdata.py", line 1229, in _write_element
write_image(
File ".../site-packages/spatialdata/_io/io_raster.py", line 371, in write_image
_write_raster(
File ".../site-packages/spatialdata/_io/io_raster.py", line 197, in _write_raster
_write_raster_dataarray(
File ".../site-packages/spatialdata/_io/io_raster.py", line 275, in _write_raster_dataarray
write_single_scale_ngff(
File ".../site-packages/ome_zarr/writer.py", line 651, in write_image
dask_delayed_jobs = _write_pyramid_to_zarr(
File ".../site-packages/ome_zarr/writer.py", line 754, in _write_pyramid_to_zarr
da.to_zarr(
File ".../site-packages/dask/array/core.py", line 4101, in to_zarr
z = root.create_array(name=array_name, **zarr_array_kwargs)
File ".../site-packages/zarr/core/group.py", line 2715, in create_array
self._sync(
File ".../site-packages/zarr/core/array.py", line 777, in _create_metadata_v3
chunk_grid_parsed = RegularChunkGrid(chunk_shape=chunk_shape)
File ".../site-packages/zarr/core/chunk_grids.py", line 180, in __init__
chunk_shape_parsed = parse_shapelike(chunk_shape)
File ".../site-packages/zarr/core/common.py", line 200, in parse_shapelike
raise TypeError(msg)
TypeError: Expected an iterable of integers. Got ((3,), (512,), (512,)) instead.
Version comparison
Failing environment:
Python 3.12.12
spatialdata 0.7.2
ome-zarr 0.14.0
zarr 3.1.5
dask 2026.1.1
Working environment:
Python 3.12.12
spatialdata 0.7.2
ome-zarr 0.13.0
zarr 3.1.5
dask 2026.1.1
So the only relevant version difference I found between the two environments is ome-zarr.
Suspected cause
It looks like spatialdata passes xarray/dask chunk metadata in the form returned by .chunks, i.e. a tuple of tuples:
In spatialdata/_io/io_raster.py, raster_data.chunks is forwarded into storage_options["chunks"]:
chunks = raster_data.chunks
...
storage_options = {"chunks": chunks}
Then in ome_zarr/writer.py, that value is forwarded into zarr_array_kwargs["chunks"]:
chunks_opt = options.pop("chunks", None)
...
zarr_array_kwargs["chunks"] = chunks_opt
But zarr expects a flat chunk shape like:
not the dask chunk grid:
Expected behavior
blobs().write(path) should succeed, or the chunk metadata should be normalized before being passed to Zarr.
Workaround
Pinning ome-zarr==0.13.0 avoids the problem in my setup.
Summary
After rebuilding a fresh environment
SpatialData.write()started failing.The same code works in an older environment with the same
spatialdata,dask, andzarrversions, but withome-zarr==0.13.0instead of0.14.0.This looks like a regression at the
spatialdata/ome-zarrboundary whenchunksare passed from xarray/dask to the writer.Minimal reproducer
Observed behavior
The call to
sdata.write(out)raises:Full traceback
Version comparison
Failing environment:
Working environment:
So the only relevant version difference I found between the two environments is
ome-zarr.Suspected cause
It looks like
spatialdatapasses xarray/dask chunk metadata in the form returned by.chunks, i.e. a tuple of tuples:In
spatialdata/_io/io_raster.py,raster_data.chunksis forwarded intostorage_options["chunks"]:Then in
ome_zarr/writer.py, that value is forwarded intozarr_array_kwargs["chunks"]:But
zarrexpects a flat chunk shape like:not the dask chunk grid:
Expected behavior
blobs().write(path)should succeed, or the chunk metadata should be normalized before being passed to Zarr.Workaround
Pinning
ome-zarr==0.13.0avoids the problem in my setup.