# Buggy code
def encode_zarr_variable(var, needs_copy=True, name=None):
    """
    Converts an Variable into an Variable which follows some
    of the CF conventions:

        - Nans are masked using _FillValue (or the deprecated missing_value)
        - Rescaling via: scale_factor and add_offset
        - datetimes are converted to the CF 'units since time' format
        - dtype encodings are enforced.

    Parameters
    ----------
    var : xarray.Variable
        A variable holding un-encoded data.

    Returns
    -------
    out : xarray.Variable
        A variable which has been encoded as described above.
    """

    if var.dtype.kind == "O":
        raise NotImplementedError(
            "Variable `%s` is an object. Zarr store can't yet encode objects." % name
        )

    for coder in [
        coding.times.CFDatetimeCoder(),
        coding.times.CFTimedeltaCoder(),
        coding.variables.CFScaleOffsetCoder(),
        coding.variables.CFMaskCoder(),
        coding.variables.UnsignedIntegerCoder(),
    ]:
        var = coder.encode(var, name=name)

    var = conventions.maybe_encode_nonstring_dtype(var, name=name)
    var = conventions.maybe_default_fill_value(var)
    var = conventions.maybe_encode_bools(var)
    var = conventions.ensure_dtype_not_object(var, name=name)
    var = conventions.maybe_encode_string_dtype(var, name=name)
    return var


# Traceback (ValueError)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-fff1cd753e7c> in <module>()
2 fs = s3fs.S3FileSystem(anon=False)
3 d = s3fs.S3Map(f_zarr, s3=fs)
----> 4 xr.open_zarr(d)

/opt/conda/lib/python3.6/site-packages/xarray/backends/zarr.py in open_zarr(store, group, synchronizer, auto_chunk, decode_cf, mask_and_scale, decode_times, concat_characters, decode_coords, drop_variables)
476
477         variables = OrderedDict([(k, maybe_chunk(k, v))
--> 478                                  for k, v in ds.variables.items()])
479         return ds._replace_vars_and_dims(variables)
480     else:

/opt/conda/lib/python3.6/site-packages/xarray/backends/zarr.py in <listcomp>(.0)
476
477         variables = OrderedDict([(k, maybe_chunk(k, v))
--> 478                                  for k, v in ds.variables.items()])
479         return ds._replace_vars_and_dims(variables)
480     else:

/opt/conda/lib/python3.6/site-packages/xarray/backends/zarr.py in maybe_chunk(name, var)
471                 token2 = tokenize(name, var._data)
472                 name2 = 'zarr-%s' % token2
--> 473                 return var.chunk(chunks, name=name2, lock=None)
474             else:
475                 return var

/opt/conda/lib/python3.6/site-packages/xarray/core/variable.py in chunk(self, chunks, name, lock)
820             data = indexing.ImplicitToExplicitIndexingAdapter(
821                 data, indexing.OuterIndexer)
--> 822             data = da.from_array(data, chunks, name=name, lock=lock)
823
824         return type(self)(self.dims, data, self._attrs, self._encoding,

/opt/conda/lib/python3.6/site-packages/dask/array/core.py in from_array(x, chunks, name, lock, asarray, fancy, getitem)
1988     >>> a = da.from_array(x, chunks=(1000, 1000), lock=True)  # doctest: +SKIP
1989     """
-> 1990     chunks = normalize_chunks(chunks, x.shape)
1991     if name in (None, True):
1992         token = tokenize(x, chunks)

/opt/conda/lib/python3.6/site-packages/dask/array/core.py in normalize_chunks(chunks, shape)
1918             raise ValueError(
1919                 "Chunks and shape must be of the same length/dimension. "
-> 1920                 "Got chunks=%s, shape=%s" % (chunks, shape))
1921
1922     if shape is not None:

ValueError: Chunks and shape must be of the same length/dimension. Got chunks=(3, 64), shape=(3,)

# Fixed code
def encode_zarr_variable(var, needs_copy=True, name=None):
    """
    Converts an Variable into an Variable which follows some
    of the CF conventions:

        - Nans are masked using _FillValue (or the deprecated missing_value)
        - Rescaling via: scale_factor and add_offset
        - datetimes are converted to the CF 'units since time' format
        - dtype encodings are enforced.

    Parameters
    ----------
    var : xarray.Variable
        A variable holding un-encoded data.

    Returns
    -------
    out : xarray.Variable
        A variable which has been encoded as described above.
    """

    var = conventions.encode_cf_variable(var, name=name)

    # zarr allows unicode, but not variable-length strings, so it's both
    # simpler and more compact to always encode as UTF-8 explicitly.
    # TODO: allow toggling this explicitly via dtype in encoding.
    coder = coding.strings.EncodedStringCoder(allows_unicode=False)
    var = coder.encode(var, name=name)
    var = coding.strings.ensure_fixed_length_bytes(var)

    return var