I was trying to concatenate two Datasets, with coords='different' meaning it will concatenate any non-matching non-index coordinates.
When one of said non-index coordinates is accidentally an IndexVariable (this ideally shouldn't happen, see #9859), we get a crash because xarray assumes it can assign to the .data attribute of a non-index coordinate.
Concatenation to succeed.
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "xarray[complete]@git+https://github.com/pydata/xarray.git@main",
# ]
# ///
#
# This script automatically imports the development branch of xarray to check for issues.
# Please delete this header if you have _not_ tested this script with `uv run`!
import xarray as xr
xr.show_versions()
# your reproducer code ...
a = xr.DataArray([0, 1, 2], dims=['x'], coords={'x': [0,1,2]})
a = a.assign_coords(foo=a.x)
b = a.assign_coords(foo=xr.Variable(['x'], [0, 0, 0]))
xr.concat([b, a], dim='new', coords='different')
See MCVE above.
In [66]: a = xr.DataArray([0, 1, 2], dims=['x'], coords={'x': [0,1,2]})
In [67]: a = a.assign_coords(foo=a.x)
In [68]: b = a.assign_coords(foo=xr.Variable(['x'], [0, 0, 0]))
In [69]: xr.concat([b, a], dim='new', coords='different')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[69], line 1
----> 1 xr.concat([b, a], dim='new', coords='different')
File /usr/lib/python3/dist-packages/xarray/core/concat.py:264, in concat(objs, dim, data_vars, coords, compat, positions, fill_value, join, combine_attrs, create_index_for_new_dim)
259 raise ValueError(
260 f"compat={compat!r} invalid: must be 'broadcast_equals', 'equals', 'identical', 'no_conflicts' or 'override'"
261 )
263 if isinstance(first_obj, DataArray):
--> 264 return _dataarray_concat(
265 objs,
266 dim=dim,
267 data_vars=data_vars,
268 coords=coords,
269 compat=compat,
270 positions=positions,
271 fill_value=fill_value,
272 join=join,
273 combine_attrs=combine_attrs,
274 create_index_for_new_dim=create_index_for_new_dim,
275 )
276 elif isinstance(first_obj, Dataset):
277 return _dataset_concat(
278 objs,
279 dim=dim,
(...)
287 create_index_for_new_dim=create_index_for_new_dim,
288 )
File /usr/lib/python3/dist-packages/xarray/core/concat.py:755, in _dataarray_concat(arrays, dim, data_vars, coords, compat, positions, fill_value, join, combine_attrs, create_index_for_new_dim)
752 arr = arr.rename(name)
753 datasets.append(arr._to_temp_dataset())
--> 755 ds = _dataset_concat(
756 datasets,
757 dim,
758 data_vars,
759 coords,
760 compat,
761 positions,
762 fill_value=fill_value,
763 join=join,
764 combine_attrs=combine_attrs,
765 create_index_for_new_dim=create_index_for_new_dim,
766 )
768 merged_attrs = merge_attrs([da.attrs for da in arrays], combine_attrs)
770 result = arrays[0]._from_temp_dataset(ds, name)
File /usr/lib/python3/dist-packages/xarray/core/concat.py:545, in _dataset_concat(datasets, dim, data_vars, coords, compat, positions, fill_value, join, combine_attrs, create_index_for_new_dim)
539 datasets = [
540 ds.expand_dims(dim_name, create_index_for_new_dim=create_index_for_new_dim)
541 for ds in datasets
542 ]
544 # determine which variables to concatenate
--> 545 concat_over, equals, concat_dim_lengths = _calc_concat_over(
546 datasets, dim_name, dim_names, data_vars, coords, compat
547 )
549 # determine which variables to merge, and then merge them according to compat
550 variables_to_merge = (coord_names | data_names) - concat_over
File /usr/lib/python3/dist-packages/xarray/core/concat.py:440, in _calc_concat_over(datasets, dim, dim_names, data_vars, coords, compat)
437 concat_over.update(opt)
439 process_subset_opt(data_vars, "data_vars")
--> 440 process_subset_opt(coords, "coords")
441 return concat_over, equals, concat_dim_lengths
File /usr/lib/python3/dist-packages/xarray/core/concat.py:406, in _calc_concat_over.<locals>.process_subset_opt(opt, subset)
401 # computed variables are not to be re-computed
402 # again in the future
403 for ds, v in zip(
404 datasets[1:], computed, strict=False
405 ):
--> 406 ds.variables[k].data = v.data
407 break
408 else:
File /usr/lib/python3/dist-packages/xarray/core/variable.py:2718, in IndexVariable.data(self, data)
2716 @Variable.data.setter # type: ignore[attr-defined]
2717 def data(self, data):
-> 2718 raise ValueError(
2719 f"Cannot assign to the .data attribute of dimension coordinate a.k.a IndexVariable {self.name!r}. "
2720 f"Please use DataArray.assign_coords, Dataset.assign_coords or Dataset.assign as appropriate."
2721 )
ValueError: Cannot assign to the .data attribute of dimension coordinate a.k.a IndexVariable 'x'. Please use DataArray.assign_coords, Dataset.assign_coords or Dataset.assign as appropriate.
What happened?
I was trying to concatenate two Datasets, with coords='different' meaning it will concatenate any non-matching non-index coordinates.
When one of said non-index coordinates is accidentally an IndexVariable (this ideally shouldn't happen, see #9859), we get a crash because xarray assumes it can assign to the
.dataattribute of a non-index coordinate.The error is:
ValueError: Cannot assign to the .data attribute of dimension coordinate a.k.a IndexVariable 'x'. Please use DataArray.assign_coords, Dataset.assign_coords or Dataset.assign as appropriate.What did you expect to happen?
Concatenation to succeed.
Minimal Complete Verifiable Example
Steps to reproduce
See MCVE above.
MVCE confirmation
Relevant log output
Anything else we need to know?
No response
Environment
Details
INSTALLED VERSIONS ------------------ commit: None python: 3.13.6 (main, Aug 7 2025, 10:53:54) [GCC 14.2.0] python-bits: 64 OS: Linux OS-release: 6.12.32-1rodete1-amd64 machine: x86_64 processor: byteorder: little LC_ALL: None LANG: en_US.UTF-8 LOCALE: ('en_US', 'UTF-8') libhdf5: 1.14.5 libnetcdf: 4.9.3xarray: 999
pandas: 2.2.3
numpy: 2.2.4
scipy: 1.15.3
netCDF4: 1.7.2
pydap: None
h5netcdf: 1.6.1
h5py: 3.13.0
zarr: 3.0.6
cftime: 1.6.4
nc_time_axis: None
iris: None
bottleneck: 1.4.2
dask: None
distributed: None
matplotlib: 3.10.1+dfsg1
cartopy: None
seaborn: None
numbagg: None
fsspec: 2025.7.0
cupy: None
pint: None
sparse: None
flox: None
numpy_groupies: None
setuptools: 78.1.1
pip3: None
conda: None
pytest: 8.3.5
mypy: None
IPython: 8.35.0
sphinx: 8.1.3