# Buggy code
def reduce(self, func, dim=None, keep_attrs=None, **kwargs):
    """Reduce the items in this group by applying `func` along some
    dimension(s).

    Parameters
    ----------
    func : function
        Function which can be called in the form
        `func(x, axis=axis, **kwargs)` to return the result of collapsing
        an np.ndarray over an integer valued axis.
    dim : `...`, str or sequence of str, optional
        Dimension(s) over which to apply `func`.
    axis : int or sequence of int, optional
        Axis(es) over which to apply `func`. Only one of the 'dimension'
        and 'axis' arguments can be supplied. If neither are supplied, then
        `func` is calculated over all dimension for each group item.
    keep_attrs : bool, optional
        If True, the datasets's attributes (`attrs`) will be copied from
        the original object to the new one.  If False (default), the new
        object will be returned without attributes.
    **kwargs : dict
        Additional keyword arguments passed on to `func`.

    Returns
    -------
    reduced : Array
        Array with summarized data and the indicated dimension(s)
        removed.
    """
    if dim is None:
        dim = self._group_dim

    if keep_attrs is None:
        keep_attrs = _get_keep_attrs(default=False)

    def reduce_dataset(ds):
        return ds.reduce(func, dim, keep_attrs, **kwargs)

    if dim is not ... and dim not in self.dims:
        raise ValueError(
            "cannot reduce over dimension %r. expected either '...' to reduce over all dimensions or one or more of %r."
            % (dim, self.dims)
        )

    return self.apply(reduce_dataset)


# Traceback (ValueError)
Traceback (most recent call last):
File "/home/travis/.PyCharmCE2019.2/config/scratches/scratch_20.py", line 13, in <module>
test = g.reduce(np.percentile, dim=('time','window'), q=0.5)
File "/home/travis/.conda/envs/Xarray/lib/python3.7/site-packages/xarray/core/groupby.py", line 800, in reduce
% (dim, self.dims)
ValueError: cannot reduce over dimension ('time', 'window'). expected either xarray.ALL_DIMS to reduce over all dimensions or one or more of ('time', 'lat', 'lon', 'window').

# Fixed code
def reduce(self, func, dim=None, keep_attrs=None, **kwargs):
    """Reduce the items in this group by applying `func` along some
    dimension(s).

    Parameters
    ----------
    func : function
        Function which can be called in the form
        `func(x, axis=axis, **kwargs)` to return the result of collapsing
        an np.ndarray over an integer valued axis.
    dim : `...`, str or sequence of str, optional
        Dimension(s) over which to apply `func`.
    axis : int or sequence of int, optional
        Axis(es) over which to apply `func`. Only one of the 'dimension'
        and 'axis' arguments can be supplied. If neither are supplied, then
        `func` is calculated over all dimension for each group item.
    keep_attrs : bool, optional
        If True, the datasets's attributes (`attrs`) will be copied from
        the original object to the new one.  If False (default), the new
        object will be returned without attributes.
    **kwargs : dict
        Additional keyword arguments passed on to `func`.

    Returns
    -------
    reduced : Array
        Array with summarized data and the indicated dimension(s)
        removed.
    """
    if dim is None:
        dim = self._group_dim

    if keep_attrs is None:
        keep_attrs = _get_keep_attrs(default=False)

    def reduce_dataset(ds):
        return ds.reduce(func, dim, keep_attrs, **kwargs)

    check_reduce_dims(dim, self.dims)

    return self.apply(reduce_dataset)