# Buggy code
def concat(cls, variables, dim="concat_dim", positions=None, shortcut=False):
    """Concatenate variables along a new or existing dimension.

    Parameters
    ----------
    variables : iterable of Array
        Arrays to stack together. Each variable is expected to have
        matching dimensions and shape except for along the stacked
        dimension.
    dim : str or DataArray, optional
        Name of the dimension to stack along. This can either be a new
        dimension name, in which case it is added along axis=0, or an
        existing dimension name, in which case the location of the
        dimension is unchanged. Where to insert the new dimension is
        determined by the first variable.
    positions : None or list of integer arrays, optional
        List of integer arrays which specifies the integer positions to
        which to assign each dataset along the concatenated dimension.
        If not supplied, objects are concatenated in the provided order.
    shortcut : bool, optional
        This option is used internally to speed-up groupby operations.
        If `shortcut` is True, some checks of internal consistency between
        arrays to concatenate are skipped.

    Returns
    -------
    stacked : Variable
        Concatenated Variable formed by stacking all the supplied variables
        along the given dimension.
    """
    if not isinstance(dim, str):
        (dim,) = dim.dims

    # can't do this lazily: we need to loop through variables at least
    # twice
    variables = list(variables)
    first_var = variables[0]

    arrays = [v.data for v in variables]

    if dim in first_var.dims:
        axis = first_var.get_axis_num(dim)
        dims = first_var.dims
        data = duck_array_ops.concatenate(arrays, axis=axis)
        if positions is not None:
            # TODO: deprecate this option -- we don't need it for groupby
            # any more.
            indices = nputils.inverse_permutation(np.concatenate(positions))
            data = duck_array_ops.take(data, indices, axis=axis)
    else:
        axis = 0
        dims = (dim,) + first_var.dims
        data = duck_array_ops.stack(arrays, axis=axis)

    attrs = dict(first_var.attrs)
    encoding = dict(first_var.encoding)
    if not shortcut:
        for var in variables:
            if var.dims != first_var.dims:
                raise ValueError("inconsistent dimensions")
            utils.remove_incompatible_items(attrs, var.attrs)

    return cls(dims, data, attrs, encoding)


# Traceback (ValueError)
In [1]: import dask.array as da; import xarray as xr; import numpy as np

In [2]: a = xr.DataArray(da.random.random((4, 6), chunks=2), attrs={'test': ['x1', 'y1']}, dims=('y', 'x'))

In [3]: b = xr.DataArray(da.random.random((4, 6), chunks=2), attrs={'test': ['x2', 'y2']}, dims=('y', 'x'))

In [4]: xr.concat([a, b], 'y')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-c8b32db4cfb7> in <module>()
----> 1 xr.concat([a, b], 'y')

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/combine.py in concat(objs, dim, data_vars, coords, compat, positions, indexers, mode, concat_over)
119         raise TypeError('can only concatenate xarray Dataset and DataArray '
120                         'objects, got %s' % type(first_obj))
--> 121     return f(objs, dim, data_vars, coords, compat, positions)
122
123

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/combine.py in _dataarray_concat(arrays, dim, data_vars, coords, compat, positions)
337
338     ds = _dataset_concat(datasets, dim, data_vars, coords, compat,
--> 339                          positions)
340     return arrays[0]._from_temp_dataset(ds, name)
341

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/combine.py in _dataset_concat(datasets, dim, data_vars, coords, compat, positions)
303         if k in concat_over:
304             vars = ensure_common_dims([ds.variables[k] for ds in datasets])
--> 305             combined = concat_vars(vars, dim, positions)
306             insert_result_variable(k, combined)
307

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/variable.py in concat(variables, dim, positions, shortcut)
1772         return IndexVariable.concat(variables, dim, positions, shortcut)
1773     else:
-> 1774         return Variable.concat(variables, dim, positions, shortcut)
1775
1776

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/variable.py in concat(cls, variables, dim, positions, shortcut)
1299                 if var.dims != first_var.dims:
1300                     raise ValueError('inconsistent dimensions')
-> 1301                 utils.remove_incompatible_items(attrs, var.attrs)
1302
1303         return cls(dims, data, attrs, encoding)

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/utils.py in remove_incompatible_items(first_dict, second_dict, compat)
157         if (k not in second_dict or
158             (k in second_dict and
--> 159                 not compat(first_dict[k], second_dict[k]))):
160             del first_dict[k]
161

~/anaconda/envs/polar2grid_py36/lib/python3.6/site-packages/xarray/core/utils.py in equivalent(first, second)
106         return ((first is second) or
107                 (first == second) or
--> 108                 (pd.isnull(first) and pd.isnull(second)))
109
110

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

# Fixed code
def concat(cls, variables, dim="concat_dim", positions=None, shortcut=False):
    """Concatenate variables along a new or existing dimension.

    Parameters
    ----------
    variables : iterable of Array
        Arrays to stack together. Each variable is expected to have
        matching dimensions and shape except for along the stacked
        dimension.
    dim : str or DataArray, optional
        Name of the dimension to stack along. This can either be a new
        dimension name, in which case it is added along axis=0, or an
        existing dimension name, in which case the location of the
        dimension is unchanged. Where to insert the new dimension is
        determined by the first variable.
    positions : None or list of integer arrays, optional
        List of integer arrays which specifies the integer positions to
        which to assign each dataset along the concatenated dimension.
        If not supplied, objects are concatenated in the provided order.
    shortcut : bool, optional
        This option is used internally to speed-up groupby operations.
        If `shortcut` is True, some checks of internal consistency between
        arrays to concatenate are skipped.

    Returns
    -------
    stacked : Variable
        Concatenated Variable formed by stacking all the supplied variables
        along the given dimension.
    """
    if not isinstance(dim, str):
        (dim,) = dim.dims

    # can't do this lazily: we need to loop through variables at least
    # twice
    variables = list(variables)
    first_var = variables[0]

    arrays = [v.data for v in variables]

    if dim in first_var.dims:
        axis = first_var.get_axis_num(dim)
        dims = first_var.dims
        data = duck_array_ops.concatenate(arrays, axis=axis)
        if positions is not None:
            # TODO: deprecate this option -- we don't need it for groupby
            # any more.
            indices = nputils.inverse_permutation(np.concatenate(positions))
            data = duck_array_ops.take(data, indices, axis=axis)
    else:
        axis = 0
        dims = (dim,) + first_var.dims
        data = duck_array_ops.stack(arrays, axis=axis)

    attrs = dict(first_var.attrs)
    encoding = dict(first_var.encoding)
    if not shortcut:
        for var in variables:
            if var.dims != first_var.dims:
                raise ValueError(
                    f"Variable has dimensions {list(var.dims)} but first Variable has dimensions {list(first_var.dims)}"
                )

    return cls(dims, data, attrs, encoding)