Skip to content

Zero-sized arrays in zarrs #352

Closed
Closed

Description

@aseyboldt

Thank you for zarrs, it is a great library!

I ran into a small issue, where zarrs fails to create arrays where one dimension has size zero:

use anyhow::Result;
use std::sync::Arc;
use zarrs::array::{ArrayBuilder, FillValue, data_type};
use zarrs::storage::store::MemoryStore;

fn main() -> Result<()> {
    let store = Arc::new(MemoryStore::new());

    // Create an array without zero dimension -- this should work fine.
    ArrayBuilder::new(
        vec![10, 20, 1],
        vec![1, 5, 1],
        data_type::float64(),
        FillValue::from(0.0f64),
    )
    .build(store.clone(), "/float_zero")?
    .store_metadata()?;

    println!("Array without zero dimension created successfully.");

    ArrayBuilder::new(
        vec![10, 20, 0],
        vec![1, 5, 0],
        data_type::float64(),
        FillValue::from(0.0f64),
    )
    .build(store.clone(), "/float_zero")?
    .store_metadata()?;

    println!("Array with zero dimension created successfully.");

    Ok(())
}

The output is

Array without zero dimension created successfully.
Error: configuration is unsupported: invalid value: integer `0`, expected a nonzero u64

This works fine in zarr:

import zarr
store = zarr.storage.MemoryStore()
array = zarr.create_array(store, name="zero_size", shape=(10, 20, 0), chunks=(1, 5, 0), dtype="float64")

zero-sized arrays come up for me surprisingly often, as special cases of more general code.

Activity

  1. LDeakin commented on Feb 14, 2026

    @LDeakin
    Member

    Thank you for zarrs, it is a great library!

    Much appreciated!

    Just wondering what do you actually want to do this these arrays? zarr-python is going to give you zarr.errors.BoundsCheckError if you try to do anything with them. Or a ZeroDivisionError: division by zero otherwise.

    I'd note that the Zarr V3 specification says this

    A shape can be the empty tuple in the case of zero-dimension arrays (scalars).

    Is that what you actually want, a scalar?

    Alternatively, if you really just want an Array with a shape of zero on any dimension, zarrs does support that. However, the regular grid is not well defined with zero-sized chunk dimensions. I'm hesitant to change that, because it breaks many of the expectations throughout the library if a chunk were to have a shape of zero.

  2. LDeakin commented on Feb 14, 2026

    @LDeakin
    Member

    @d-v-b any thoughts on if chunks=(1, 5, 0) should just be rejected by zarr-python?

  3. aseyboldt commented on Feb 16, 2026

    @aseyboldt
    Author

    Ah sorry, I get it now, this was my mistake...

    I really do want an array with one axis being zero, and it works just fine if I set a non-zero chunk size. I had tried that as well, but it then failed (correctly, I think) when I then tried to write an empty chunk. I just should not write empty chunks...

    Thanks for checking though!

  4. d-v-b commented on Feb 16, 2026

    @d-v-b

    @d-v-b any thoughts on if chunks=(1, 5, 0) should just be rejected by zarr-python?

    I think the regular chunk grid spec allows it? At least I can't see where it's explicitly disallowed. We do allow this in zarr python, but I'm guessing that's a side-effect of design rather than trying to be comprehensive. I could be wrong though.

  5. LDeakin commented on Feb 16, 2026

    @LDeakin
    Member

    The division and modulo operations are undefined with zeros

  6. d-v-b commented on Feb 16, 2026

    @d-v-b

    so they are! in that case zarr-python is out of spec and this needs to be fixed. I assume there are some folks who rely on this feature, so we might end up with a conversation in the spec repo...

  7. d-v-b commented on Feb 16, 2026

    @d-v-b

    although nobody can have relied on this too much: we don't support accessing the values of such arrays once created:

    >>> zarr.zeros(store={}, shape=(1,5,1), chunks=(1,2,0))[:]    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/d-v-b/dev/data-model-1/.venv/lib/python3.12/site-packages/zarr/core/array.py", line 2868, in __getitem__
        return self.get_orthogonal_selection(pure_selection, fields=fields)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/d-v-b/dev/data-model-1/.venv/lib/python3.12/site-packages/zarr/core/array.py", line 3338, in get_orthogonal_selection
        indexer = OrthogonalIndexer(selection, self.shape, self.metadata.chunk_grid)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/d-v-b/dev/data-model-1/.venv/lib/python3.12/site-packages/zarr/core/indexing.py", line 923, in __init__
        dim_indexer = SliceDimIndexer(dim_sel, dim_len, dim_chunk_len)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/d-v-b/dev/data-model-1/.venv/lib/python3.12/site-packages/zarr/core/indexing.py", line 424, in __init__
        object.__setattr__(self, "nchunks", ceildiv(dim_len, dim_chunk_len))
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/d-v-b/dev/data-model-1/.venv/lib/python3.12/site-packages/zarr/core/common.py", line 94, in ceildiv
        return math.ceil(a / b)
                         ~~^~~
    ZeroDivisionError: division by zero
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions